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 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 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 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 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 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 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 162 void deInitShaderPrograms() 163 { 164 glDeleteProgram(sShaderFlat.program); 165 glDeleteProgram(sShaderLit.program); 166 glDeleteProgram(sShaderFade.program); 167 } 168 169 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