Subversion Repositories AndroidProjects

Rev

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