/////////////////////////////////////////// uniform vec4 draw_texture_coords; uniform vec2 draw_texture_dims; uniform mediump vec4 draw_texture_normalized_crop_rect[kMaxTexUnits]; // Varyings///////////////////////////////////////////////////////////////////// out vec4 pos_varying; out vec3 normal_varying; out mediump vec4 color_varying; flat out mediump vec4 color_varying_flat; #if kTexUnits >= 1u out mediump vec3 texcoord0_varying; #endif #if kTexUnits >= 2u out mediump vec3 texcoord1_varying; #endif #if kTexUnits >= 3u out mediump vec3 texcoord2_varying; #endif #if kTexUnits >= 4u out mediump vec3 texcoord3_varying; #endif float posDot(vec3 a, vec3 b) { return max(dot(a, b), 0.0); } mediump vec4 doLighting(mediump vec4 vertexColor) { mediump vec4 materialAmbientActual = material_ambient; mediump vec4 materialDiffuseActual = material_diffuse; if (enable_color_material) { materialAmbientActual = vertexColor; materialDiffuseActual = vertexColor; } mediump vec4 lightingResult = material_emissive + materialAmbientActual * light_model_scene_ambient; for (uint i = 0u; i < kMaxLights; i++) { if (!light_enables[i]) continue; mediump vec4 lightAmbient = light_ambients[i]; mediump vec4 lightDiffuse = light_diffuses[i]; mediump vec4 lightSpecular = light_speculars[i]; vec4 lightPos = light_positions[i]; vec3 lightDir = light_directions[i]; float attConst = light_attenuation_consts[i]; float attLinear = light_attenuation_linears[i]; float attQuadratic = light_attenuation_quadratics[i]; float spotAngle = light_spotlight_cutoff_angles[i]; float spotExponent = light_spotlight_exponents[i]; vec3 toLight; if (lightPos.w == 0.0) { toLight = lightPos.xyz; } else { toLight = (lightPos.xyz / lightPos.w - pos_varying.xyz); } float lightDist = length(toLight); vec3 toLightNormalized = normalize(toLight); vec3 h = toLightNormalized + vec3(0.0, 0.0, 1.0); float ndotL = posDot(normal_varying, toLightNormalized); float ndoth = posDot(normal_varying, normalize(h)); float specAtt; if (ndotL != 0.0) { specAtt = 1.0; } else { specAtt = 0.0; } float att; if (lightPos.w != 0.0) { float attDenom = (attConst + attLinear * lightDist + attQuadratic * lightDist * lightDist); att = 1.0 / attDenom; } else { att = 1.0; } mediump float spot; mediump float spotAngleCos = cos(radians(spotAngle)); vec3 toSurfaceDir = -toLightNormalized; mediump float spotDot = posDot(toSurfaceDir, normalize(lightDir)); if (spotAngle == 180.0 || lightPos.w == 0.0) { spot = 1.0; } else { if (spotDot < spotAngleCos) { spot = 0.0; } else { spot = pow(spotDot, spotExponent); } } mediump vec4 contrib = materialAmbientActual * lightAmbient; contrib += ndotL * materialDiffuseActual * lightDiffuse; if (ndoth > 0.0 && material_specular_exponent > 0.0) { contrib += specAtt * pow(ndoth, material_specular_exponent) * material_specular * lightSpecular; } else { if (ndoth > 0.0) { contrib += specAtt * material_specular * lightSpecular; } } contrib *= att * spot; lightingResult += contrib; } return lightingResult; } const mediump vec4 drawTextureVertices[6] = vec4[]( vec4(0.0, 0.0, 0.0, 1.0), vec4(1.0, 0.0, 0.0, 1.0), vec4(1.0, 1.0, 0.0, 1.0), vec4(0.0, 0.0, 0.0, 1.0), vec4(1.0, 1.0, 0.0, 1.0), vec4(0.0, 1.0, 0.0, 1.0)); mediump vec4 drawTexturePosition(int vertexId) { // The texture is drawn in the XY plane, so Z is constant. vec2 positionXY = draw_texture_coords.xy + drawTextureVertices[vertexId].xy * draw_texture_dims; return vec4(positionXY, draw_texture_coords.z, 1.0); } mediump vec3 drawTextureTexCoord(int vertexId, uint textureUnit) { // The texture is drawn in the XY plane, so Z is 0. mediump vec2 texCropPos = draw_texture_normalized_crop_rect[textureUnit].xy; mediump vec2 texCropDim = draw_texture_normalized_crop_rect[textureUnit].zw; mediump vec2 texCoords = texCropPos + drawTextureVertices[vertexId].xy * texCropDim; return vec3(texCoords, 0.0); } vec4 calcWorldPosition(vec4 posInput) { return modelview * posInput; } vec4 calcNdcFromWorldPosition(vec4 worldPos) { return projection * worldPos; } float calcPointSize(vec4 ndcPos) { float dist = length(ndcPos.z); float attConst = point_distance_attenuation[0]; float attLinear = point_distance_attenuation[1]; float attQuad = point_distance_attenuation[2]; float attPart = attConst + attLinear * dist + attQuad * dist * dist; float attPointSize = pointsize / pow(attPart, 0.5); return clamp(attPointSize, point_size_min, point_size_max); } vec3 calcNormal(vec3 normalInput) { mat3 mvInvTr3 = mat3(modelview_invtr); vec3 result = mvInvTr3 * normalInput; if (enable_rescale_normal) { float rescale = 1.0; vec3 rescaleVec = vec3(mvInvTr3[2]); float len = length(rescaleVec); if (len > 0.0) { rescale = 1.0 / len; } result *= rescale; } if (enable_normalize) { result = normalize(result); } return result; } void main() { if (enable_draw_texture) { int vertexId = gl_VertexID; mediump vec4 posDrawTexture = drawTexturePosition(vertexId); gl_Position = posDrawTexture; pos_varying = posDrawTexture; normal_varying = normal; gl_PointSize = pointsize; #if kTexUnits >= 1u texcoord0_varying = drawTextureTexCoord(vertexId, 0u); #endif #if kTexUnits >= 2u texcoord1_varying = drawTextureTexCoord(vertexId, 1u); #endif #if kTexUnits >= 3u texcoord2_varying = drawTextureTexCoord(vertexId, 2u); #endif #if kTexUnits >= 4u texcoord3_varying = drawTextureTexCoord(vertexId, 3u); #endif } else { vec4 worldPos = calcWorldPosition(pos); vec4 ndcPos = calcNdcFromWorldPosition(worldPos); gl_Position = ndcPos; pos_varying = worldPos; normal_varying = calcNormal(normal); // Avoid calculating point size stuff // if we are not rendering points. if (point_rasterization) { gl_PointSize = calcPointSize(ndcPos); } else { gl_PointSize = pointsize; } #if kTexUnits >= 1u texcoord0_varying = (texture_matrix[0] * texcoord0).xyz; #endif #if kTexUnits >= 2u texcoord1_varying = (texture_matrix[1] * texcoord1).xyz; #endif #if kTexUnits >= 3u texcoord2_varying = (texture_matrix[2] * texcoord2).xyz; #endif #if kTexUnits >= 4u texcoord3_varying = (texture_matrix[3] * texcoord3).xyz; #endif } mediump vec4 vertex_color = color; if (enable_lighting) { vertex_color = doLighting(color); } vertex_color = clamp(vertex_color, vec4(0), vec4(1)); color_varying = vertex_color; color_varying_flat = vertex_color; }