1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Adapted from the javascript implementation upon WebGL by kwaters@.
6
7 #include "shader.h"
8
9 #include <stdio.h>
10 #include <stdlib.h>
11
12 #include "shadersrc.h"
13
14 #undef IMPORTGL_API
15 #undef IMPORTGL_FNPTRINIT
16 #include "importgl.h"
17
18
19 SHADERLIT sShaderLit;
20 SHADERFLAT sShaderFlat;
21 SHADERFADE sShaderFade;
22
23 Matrix4x4 sModelView;
24 Matrix4x4 sProjection;
25
26
printShaderLog(GLuint shader)27 static void printShaderLog(GLuint shader)
28 {
29 int infoLogSize, infoWritten;
30 char *infoLog;
31 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogSize);
32 infoLog = malloc(infoLogSize);
33 glGetShaderInfoLog(shader, infoLogSize, &infoWritten, infoLog);
34 fprintf(stderr, "Error: glCompileShader failed: %s\n", infoLog);
35 free(infoLog);
36 }
37
38
createShader(const char * src,GLenum shaderType)39 static GLuint createShader(const char *src, GLenum shaderType)
40 {
41 GLint bShaderCompiled;
42 GLuint shader = glCreateShader(shaderType);
43 if (shader == 0)
44 return 0;
45 glShaderSource(shader, 1, &src, NULL);
46 glCompileShader(shader);
47 glGetShaderiv(shader, GL_COMPILE_STATUS, &bShaderCompiled);
48 if (!bShaderCompiled)
49 {
50 printShaderLog(shader);
51 glDeleteShader(shader);
52 return 0;
53 }
54 return shader;
55 }
56
57
createProgram(const char * srcVertex,const char * srcFragment)58 static GLuint createProgram(const char *srcVertex, const char * srcFragment)
59 {
60 GLuint program = glCreateProgram();
61 if (program == 0)
62 return 0;
63
64 GLuint shaderVertex = createShader(srcVertex, GL_VERTEX_SHADER);
65 if (shaderVertex == 0)
66 {
67 glDeleteProgram(program);
68 return 0;
69 }
70 glAttachShader(program, shaderVertex);
71 glDeleteShader(shaderVertex);
72
73 GLuint shaderFragment = createShader(srcFragment, GL_FRAGMENT_SHADER);
74 if (shaderFragment == 0)
75 {
76 glDeleteProgram(program);
77 return 0;
78 }
79 glAttachShader(program, shaderFragment);
80 glDeleteShader(shaderFragment);
81
82 glLinkProgram(program);
83 return program;
84 }
85
86
computeNormalMatrix(Matrix4x4 m,Matrix3x3 normal)87 static void computeNormalMatrix(Matrix4x4 m, Matrix3x3 normal)
88 {
89 float det = m[0*4+0] * (m[1*4+1] * m[2*4+2] - m[2*4+1] * m[1*4+2]) -
90 m[0*4+1] * (m[1*4+0] * m[2*4+2] - m[1*4+2] * m[2*4+0]) +
91 m[0*4+2] * (m[1*4+0] * m[2*4+1] - m[1*4+1] * m[2*4+0]);
92 float invDet = 1.f / det;
93 normal[0*3+0] = invDet * (m[1*4+1] * m[2*4+2] - m[2*4+1] * m[1*4+2]);
94 normal[1*3+0] = invDet * -(m[0*4+1] * m[2*4+2] - m[0*4+2] * m[2*4+1]);
95 normal[2*3+0] = invDet * (m[0*4+1] * m[1*4+2] - m[0*4+2] * m[1*4+1]);
96 normal[0*3+1] = invDet * -(m[1*4+0] * m[2*4+2] - m[1*4+2] * m[2*4+0]);
97 normal[1*3+1] = invDet * (m[0*4+0] * m[2*4+2] - m[0*4+2] * m[2*4+0]);
98 normal[2*3+1] = invDet * -(m[0*4+0] * m[1*4+2] - m[1*4+0] * m[0*4+2]);
99 normal[0*3+2] = invDet * (m[1*4+0] * m[2*4+1] - m[2*4+0] * m[1*4+1]);
100 normal[1*3+2] = invDet * -(m[0*4+0] * m[2*4+1] - m[2*4+0] * m[0*4+1]);
101 normal[2*3+2] = invDet * (m[0*4+0] * m[1*4+1] - m[1*4+0] * m[0*4+1]);
102 }
103
104
getLocations()105 static int getLocations()
106 {
107 int rt = 1;
108 #define GET_ATTRIBUTE_LOC(programName, varName) \
109 sShader##programName.varName = \
110 glGetAttribLocation(sShader##programName.program, #varName); \
111 if (sShader##programName.varName == -1) rt = 0
112 #define GET_UNIFORM_LOC(programName, varName) \
113 sShader##programName.varName = \
114 glGetUniformLocation(sShader##programName.program, #varName); \
115 if (sShader##programName.varName == -1) rt = 0
116 GET_ATTRIBUTE_LOC(Lit, pos);
117 GET_ATTRIBUTE_LOC(Lit, normal);
118 GET_ATTRIBUTE_LOC(Lit, colorIn);
119 GET_UNIFORM_LOC(Lit, mvp);
120 GET_UNIFORM_LOC(Lit, normalMatrix);
121 GET_UNIFORM_LOC(Lit, ambient);
122 GET_UNIFORM_LOC(Lit, shininess);
123 GET_UNIFORM_LOC(Lit, light_0_direction);
124 GET_UNIFORM_LOC(Lit, light_0_diffuse);
125 GET_UNIFORM_LOC(Lit, light_0_specular);
126 GET_UNIFORM_LOC(Lit, light_1_direction);
127 GET_UNIFORM_LOC(Lit, light_1_diffuse);
128 GET_UNIFORM_LOC(Lit, light_2_direction);
129 GET_UNIFORM_LOC(Lit, light_2_diffuse);
130
131 GET_ATTRIBUTE_LOC(Flat, pos);
132 GET_ATTRIBUTE_LOC(Flat, colorIn);
133 GET_UNIFORM_LOC(Flat, mvp);
134
135 GET_ATTRIBUTE_LOC(Fade, pos);
136 GET_UNIFORM_LOC(Fade, minFade);
137 #undef GET_ATTRIBUTE_LOC
138 #undef GET_UNIFORM_LOC
139 return rt;
140 }
141
142
initShaderPrograms()143 int initShaderPrograms()
144 {
145 Matrix4x4_LoadIdentity(sModelView);
146 Matrix4x4_LoadIdentity(sProjection);
147
148 sShaderFlat.program = createProgram(sFlatVertexSource,
149 sFlatFragmentSource);
150 sShaderLit.program = createProgram(sLitVertexSource,
151 sFlatFragmentSource);
152 sShaderFade.program = createProgram(sFadeVertexSource,
153 sFlatFragmentSource);
154 if (sShaderFlat.program == 0 || sShaderLit.program == 0 ||
155 sShaderFade.program == 0)
156 return 0;
157
158 return getLocations();
159 }
160
161
deInitShaderPrograms()162 void deInitShaderPrograms()
163 {
164 glDeleteProgram(sShaderFlat.program);
165 glDeleteProgram(sShaderLit.program);
166 glDeleteProgram(sShaderFade.program);
167 }
168
169
bindShaderProgram(GLuint program)170 void bindShaderProgram(GLuint program)
171 {
172 int loc_mvp = -1;
173 int loc_normalMatrix = -1;
174
175 glUseProgram(program);
176
177 if (program == sShaderLit.program)
178 {
179 loc_mvp = sShaderLit.mvp;
180 loc_normalMatrix = sShaderLit.normalMatrix;
181 }
182 else if (program == sShaderFlat.program)
183 {
184 loc_mvp = sShaderFlat.mvp;
185 }
186
187 if (loc_mvp != -1)
188 {
189 Matrix4x4 mvp;
190 Matrix4x4_Multiply(mvp, sModelView, sProjection);
191 glUniformMatrix4fv(loc_mvp, 1, GL_FALSE, (GLfloat *)mvp);
192 }
193 if (loc_normalMatrix != -1)
194 {
195 Matrix3x3 normalMatrix;
196 computeNormalMatrix(sModelView, normalMatrix);
197 glUniformMatrix3fv(loc_normalMatrix, 1, GL_FALSE,
198 (GLfloat *)normalMatrix);
199 }
200 }
201
202