Home | History | Annotate | Download | only in src
      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