Subversion Repositories AndroidProjects

Rev

Rev 1712 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1712 chris 1
package com.gebauz.bauzoid2.graphics.shader;
2
 
3
import java.nio.IntBuffer;
4
import java.util.ArrayList;
5
import java.util.List;
6
 
7
import com.badlogic.gdx.Gdx;
8
import com.badlogic.gdx.graphics.GL20;
9
import com.badlogic.gdx.utils.BufferUtils;
10
import com.gebauz.bauzoid2.game.Engine;
11
import com.gebauz.bauzoid2.graphics.geometry.VertexAttribute;
1743 chris 12
import com.gebauz.bauzoid2.math.Matrix3;
1712 chris 13
import com.gebauz.bauzoid2.math.Matrix4;
14
 
15
public class ShaderProgram
16
{
17
        private static List<ShaderProgram> mManagedShaders = new ArrayList<ShaderProgram>();
18
 
19
        public static String ATTRIB_POSITION = "aPosition";
20
        public static String ATTRIB_COLOR = "aColor";
21
        public static String ATTRIB_NORMAL= "aNormal";
22
        public static String ATTRIB_TEXCOORD0 = "aTexCoord0";
23
        public static String ATTRIB_TEXCOORD1 = "aTexCoord1";
24
        public static String ATTRIB_BLENDINDICES = "aBlendIndex";
25
        public static String ATTRIB_BLENDWEIGHTS = "aBlendWeight";
26
 
27
        public static String UNIFORM_MVP_MATRIX = "uMVPMatrix";
1743 chris 28
    public static String UNIFORM_NORMAL_MATRIX = "uNormalMatrix";
1712 chris 29
 
30
        public class Shader
31
        {
32
                private int mShaderID = 0;
33
                private int mShaderType;
34
                private String mShaderCode;
35
 
36
                public Shader(int shaderType)
37
                {
38
                        mShaderType = shaderType;
39
                }
40
 
41
                public void loadShader(String shaderCode)
42
                {
43
                        ShaderUtil.log("Loading " + (mShaderType == GL20.GL_VERTEX_SHADER ? "Vertex" : "Fragment") + " Shader");
44
 
45
                        mShaderCode = shaderCode;
46
 
47
                        if (mShaderID != 0)
48
                                unloadShader();
49
 
50
                        mShaderID = Gdx.gl20.glCreateShader(mShaderType);
51
 
52
                        Gdx.gl20.glShaderSource(mShaderID, mShaderCode);
53
                        Gdx.gl20.glCompileShader(mShaderID);
54
 
55
                        Gdx.gl20.glGetShaderiv(mShaderID, GL20.GL_COMPILE_STATUS, COMPILESTATUS);
56
 
57
                        if (COMPILESTATUS.get(0) != GL20.GL_TRUE)
58
                        {
59
                                ShaderUtil.logError("Shader Error: " + Gdx.gl20.glGetShaderInfoLog(mShaderID));
60
                                return;
61
                        }
62
 
63
                        ShaderUtil.log("Shader loading successful!");
64
                }
65
 
66
                public void reloadShader()
67
                {                      
68
                        mShaderID = 0;
69
                        loadShader(mShaderCode);
70
                }
71
 
72
                public void unloadShader()
73
                {
74
                        Gdx.gl20.glDeleteShader(mShaderID);
75
                        mShaderID = 0;
76
                        mShaderCode = "";
77
                }
78
        };
79
 
80
        private static final IntBuffer COMPILESTATUS = BufferUtils.newIntBuffer(1);
81
 
82
        private Shader mVertexShader = null;
83
        private Shader mFragmentShader = null;
84
        private int mProgramID = 0;
85
 
86
        // Standard uniforms
1743 chris 87
        private ShaderUniform mModelViewProjectionHandle = null;
1712 chris 88
        private Matrix4 mModelViewProjectionMatrix = new Matrix4();
1743 chris 89
 
90
    private ShaderUniform mNormalHandle = null;
91
    private Matrix3 mNormalMatrix = new Matrix3();
1712 chris 92
 
93
        public ShaderProgram()
94
        {
95
                mVertexShader = new Shader(GL20.GL_VERTEX_SHADER);
96
                mFragmentShader = new Shader(GL20.GL_FRAGMENT_SHADER);
97
        }
98
 
99
        public void loadShaderProgram(String vertexShaderCode, String fragmentShaderCode)
100
        {
101
                mVertexShader.loadShader(vertexShaderCode);
102
                mFragmentShader.loadShader(fragmentShaderCode);
103
 
104
                mProgramID = Gdx.gl20.glCreateProgram();
105
 
106
                Gdx.gl20.glAttachShader(mProgramID, mVertexShader.mShaderID);
107
                Gdx.gl20.glAttachShader(mProgramID, mFragmentShader.mShaderID);
108
 
109
                // default attrib locations
110
                /*GLES20.glBindAttribLocation(mProgramID, SimpleGeometry.COORD_ATTRIB_INDEX, "vPosition");
111
                GLES20.glBindAttribLocation(mProgramID, SimpleGeometry.COLOR_ATTRIB_INDEX, "vColor");
112
                GLES20.glBindAttribLocation(mProgramID, SimpleGeometry.NORMAL_ATTRIB_INDEX, "vNormal");
113
                GLES20.glBindAttribLocation(mProgramID, SimpleGeometry.TEX_COORD_ATTRIB_INDEX, "vTexCoord");*/
114
 
115
                Gdx.gl20.glBindAttribLocation(mProgramID, VertexAttribute.POSITION, ATTRIB_POSITION);
116
                Gdx.gl20.glBindAttribLocation(mProgramID, VertexAttribute.COLOR, ATTRIB_COLOR);
117
                Gdx.gl20.glBindAttribLocation(mProgramID, VertexAttribute.NORMAL, ATTRIB_NORMAL);
118
                Gdx.gl20.glBindAttribLocation(mProgramID, VertexAttribute.TEXCOORD0, ATTRIB_TEXCOORD0);
119
                Gdx.gl20.glBindAttribLocation(mProgramID, VertexAttribute.TEXCOORD1, ATTRIB_TEXCOORD1);
120
                Gdx.gl20.glBindAttribLocation(mProgramID, VertexAttribute.BLENDINDICES, ATTRIB_BLENDINDICES);
121
                Gdx.gl20.glBindAttribLocation(mProgramID, VertexAttribute.BLENDWEIGHTS, ATTRIB_BLENDWEIGHTS);
122
 
123
                Gdx.gl20.glLinkProgram(mProgramID);
1743 chris 124
 
125
        Engine.log(Gdx.gl20.glGetProgramInfoLog(mProgramID));
1712 chris 126
 
127
                // obtain uniforms for standard names
1743 chris 128
                mModelViewProjectionHandle = getStandardUniform(UNIFORM_MVP_MATRIX);
129
        mNormalHandle = getStandardUniform(UNIFORM_NORMAL_MATRIX);
1712 chris 130
 
131
                mManagedShaders.add(this);
132
        }
133
 
134
        public ShaderUniform getStandardUniform(String uniformName)
135
        {
136
                if (existsUniform(uniformName))
137
                        return getUniform(uniformName);
138
 
139
                return null;
140
        }
141
 
142
        public void reloadShaderProgram()
143
        {
144
                mVertexShader.reloadShader();
145
                mFragmentShader.reloadShader();
146
 
147
                mProgramID = Gdx.gl20.glCreateProgram();
148
 
149
                Gdx.gl20.glAttachShader(mProgramID, mVertexShader.mShaderID);
150
                Gdx.gl20.glAttachShader(mProgramID, mFragmentShader.mShaderID);
151
 
152
                // default attrib locations
153
                Gdx.gl20.glBindAttribLocation(mProgramID, VertexAttribute.POSITION, ATTRIB_POSITION);
154
                Gdx.gl20.glBindAttribLocation(mProgramID, VertexAttribute.COLOR, ATTRIB_COLOR);
155
                Gdx.gl20.glBindAttribLocation(mProgramID, VertexAttribute.NORMAL, ATTRIB_NORMAL);
156
                Gdx.gl20.glBindAttribLocation(mProgramID, VertexAttribute.TEXCOORD0, ATTRIB_TEXCOORD0);
157
                Gdx.gl20.glBindAttribLocation(mProgramID, VertexAttribute.TEXCOORD1, ATTRIB_TEXCOORD1);
158
                Gdx.gl20.glBindAttribLocation(mProgramID, VertexAttribute.BLENDINDICES, ATTRIB_BLENDINDICES);
159
                Gdx.gl20.glBindAttribLocation(mProgramID, VertexAttribute.BLENDWEIGHTS, ATTRIB_BLENDWEIGHTS);
160
 
161
                Gdx.gl20.glLinkProgram(mProgramID);
162
        }
163
 
164
        public void dispose()
165
        {
166
                mManagedShaders.remove(this);
167
 
168
                Gdx.gl20.glDeleteProgram(mProgramID);  
169
 
170
                mVertexShader.unloadShader();
171
                mFragmentShader.unloadShader();
172
 
173
                mProgramID = 0;
174
        }
175
 
176
        public void activate()
177
        {
178
                // TODO: state management!
179
                Gdx.gl20.glUseProgram(mProgramID);
180
 
181
                // apply standard uniforms
1743 chris 182
                if (mModelViewProjectionHandle != null)
1712 chris 183
                {
184
                        Engine.graphics.renderStates.getModelViewProjection(mModelViewProjectionMatrix);
1743 chris 185
                        mModelViewProjectionHandle.set(mModelViewProjectionMatrix);
1712 chris 186
                }
1743 chris 187
        if (mNormalHandle != null)
188
        {
189
            Engine.graphics.renderStates.getModelViewProjection(mModelViewProjectionMatrix);
190
 
191
            mNormalMatrix = mModelViewProjectionMatrix.toMatrix3().getInverse().getTranspose();
192
            mNormalHandle.set(mNormalMatrix);
193
        }
1712 chris 194
        }
195
 
196
        public void deactivate()
197
        {
198
                Gdx.gl20.glUseProgram(0);
199
        }
200
 
201
        public ShaderUniform getUniform(String uniformName)
202
        {
203
                if (mProgramID == 0)
204
                        return null;
205
 
206
                int handle = getUniformHandle(uniformName);
207
 
208
                if (handle == -1)
209
                {
210
                        ShaderUtil.logError("Error getting uniform '" + uniformName + "'!");
211
                        return null;
212
                }
213
 
214
                return new ShaderUniform(this, uniformName);
215
        }
216
 
217
        public boolean existsUniform(String uniformName)
218
        {
219
                if (mProgramID == 0)
220
                        return false;
221
 
222
                return (getUniformHandle(uniformName) != -1);
223
        }
224
 
225
        public int getUniformHandle(String uniformName)
226
        {
227
                return Gdx.gl20.glGetUniformLocation(mProgramID, uniformName);
228
        }
229
 
230
        public Shader getVertexShader()
231
        {
232
                return mVertexShader;
233
        }
234
 
235
        public Shader getFragmentShader()
236
        {
237
                return mFragmentShader;
238
        }
239
 
240
        public static void reloadManagedShaders()
241
        {
242
                for (int i = 0; i < mManagedShaders.size(); i++)
243
                {
244
                        ShaderProgram shader = mManagedShaders.get(i);
245
                        shader.reloadShaderProgram();
246
                        ShaderUtil.log("ShaderProgram reloaded!");
247
                }
248
        }
249
}
250
 
251