// #### bindProgram // // Do all the work to build and install shader including // set up buffer blocks for uniform variables, set up // default lighting parameters, pass material uniforms // and bind texture buffers used by texture maps and by // OpenSubdiv's built-in shading code. // GLuint OpenSubdivShader::bindProgram(const MHWRender::MDrawContext & mDrawContext, OpenSubdiv::OsdGLDrawContext *osdDrawContext, const OpenSubdiv::OsdDrawContext::PatchArray & patch) { CHECK_GL_ERROR("bindProgram begin\n"); // Primitives are triangles for Loop subdivision, quads otherwise Effect effect = kFill; EffectDesc effectDesc( patch.GetDescriptor(), effect ); // Build shader EffectDrawRegistry::ConfigType * config = g_effectRegistry.GetDrawConfig(effectDesc); // Install shader GLuint program = config->program; glUseProgram(program); // Update and bind transform state struct Transform { float ModelViewMatrix[16]; float ProjectionMatrix[16]; float ModelViewProjectionMatrix[16]; } transformData; setMatrix(mDrawContext.getMatrix(MHWRender::MDrawContext::kWorldViewMtx), transformData.ModelViewMatrix); setMatrix(mDrawContext.getMatrix(MHWRender::MDrawContext::kProjectionMtx), transformData.ProjectionMatrix); setMatrix(mDrawContext.getMatrix(MHWRender::MDrawContext::kWorldViewProjMtx), transformData.ModelViewProjectionMatrix); if (!g_transformUB) { glGenBuffers(1, &g_transformUB); glBindBuffer(GL_UNIFORM_BUFFER, g_transformUB); glBufferData(GL_UNIFORM_BUFFER, sizeof(transformData), NULL, GL_STATIC_DRAW); }; glBindBuffer(GL_UNIFORM_BUFFER, g_transformUB); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(transformData), &transformData); glBindBuffer(GL_UNIFORM_BUFFER, 0); glBindBufferBase(GL_UNIFORM_BUFFER, g_transformBinding, g_transformUB); // Update and bind tessellation state struct Tessellation { float TessLevel; } tessellationData; tessellationData.TessLevel = static_cast<float>(1 << _tessFactor); if (!g_tessellationUB) { glGenBuffers(1, &g_tessellationUB); glBindBuffer(GL_UNIFORM_BUFFER, g_tessellationUB); glBufferData(GL_UNIFORM_BUFFER, sizeof(tessellationData), NULL, GL_STATIC_DRAW); }; glBindBuffer(GL_UNIFORM_BUFFER, g_tessellationUB); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(tessellationData), &tessellationData); glBindBuffer(GL_UNIFORM_BUFFER, 0); glBindBufferBase(GL_UNIFORM_BUFFER, g_tessellationBinding, g_tessellationUB); // Update and bind lighting state int numLights = mDrawContext.numberOfActiveLights(); struct Lighting { struct Light { float position[4]; float diffuse[4]; float ambient[4]; float specular[4]; } lightSource[2]; } lightingData; memset(&lightingData, 0, sizeof(lightingData)); for (int i = 0; i < numLights && i < 2; ++i) { MFloatPointArray positions; MFloatVector direction; float intensity; MColor color; bool hasDirection, hasPosition; mDrawContext.getLightInformation(i, positions, direction, intensity, color, hasDirection, hasPosition); MMatrix modelView = mDrawContext.getMatrix(MHWRender::MDrawContext::kWorldViewMtx); direction = MVector(direction) * modelView; Lighting::Light &light = lightingData.lightSource[i]; if (hasDirection) { light.position[0] = -direction[0]; light.position[1] = -direction[1]; light.position[2] = -direction[2]; for (int j = 0; j < 4; ++j) { light.diffuse[j] = color[j] * intensity; light.ambient[j] = color[j] * intensity; light.specular[j] = color[j] * intensity; } } } if (!g_lightingUB) { glGenBuffers(1, &g_lightingUB); glBindBuffer(GL_UNIFORM_BUFFER, g_lightingUB); glBufferData(GL_UNIFORM_BUFFER, sizeof(lightingData), NULL, GL_STATIC_DRAW); }; glBindBuffer(GL_UNIFORM_BUFFER, g_lightingUB); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(lightingData), &lightingData); glBindBuffer(GL_UNIFORM_BUFFER, 0); glBindBufferBase(GL_UNIFORM_BUFFER, g_lightingBinding, g_lightingUB); // Update other uniforms float color[4] = { 0, 0, 0, 1 }; _diffuse.get(color); glProgramUniform4fv(program, glGetUniformLocation(program, "diffuseColor"), 1, color); _ambient.get(color); glProgramUniform4fv(program, glGetUniformLocation(program, "ambientColor"), 1, color); _specular.get(color); glProgramUniform4fv(program, glGetUniformLocation(program, "specularColor"), 1, color); glProgramUniform1f(program, glGetUniformLocation(program, "shininess"), _shininess); // Bind diffuse map if (g_effectRegistry.getDiffuseId()!=0) { GLint difmap = glGetUniformLocation(program, "diffuseMap"); glProgramUniform1i(program, difmap, DIFF_TEXTURE_UNIT); } // Bind all texture buffers // OpenSubdiv's geometric shading code depends on additional // GL texture buffers. These are managed by the DrawContext // and must be bound for use by the program in addition to // any buffers used by the client/application shading code. if (osdDrawContext->GetVertexTextureBuffer()) { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_BUFFER, osdDrawContext->GetVertexTextureBuffer()); } if (osdDrawContext->GetVertexValenceTextureBuffer()) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_BUFFER, osdDrawContext->GetVertexValenceTextureBuffer()); } if (osdDrawContext->GetQuadOffsetsTextureBuffer()) { glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_BUFFER, osdDrawContext->GetQuadOffsetsTextureBuffer()); } if (osdDrawContext->GetPatchParamTextureBuffer()) { glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_BUFFER, osdDrawContext->GetPatchParamTextureBuffer()); } if (osdDrawContext->GetFvarDataTextureBuffer()) { glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_BUFFER, osdDrawContext->GetFvarDataTextureBuffer() ); } glActiveTexture(GL_TEXTURE0); CHECK_GL_ERROR("bindProgram leave\n"); return program; }
GLuint OpenSubdivPtexShader::bindProgram(const MHWRender::MDrawContext & mDrawContext, OpenSubdiv::OsdGLDrawContext *osdDrawContext, const OpenSubdiv::OsdPatchArray & patch) { CHECK_GL_ERROR("bindProgram begin\n"); // Build shader Effect effect; effect.color = _enableColor; effect.occlusion = _enableOcclusion; effect.displacement = _enableDisplacement; effect.normal = _enableNormal; EffectDesc effectDesc( patch.desc, effect ); EffectDrawRegistry::ConfigType * config = effectRegistry.GetDrawConfig(effectDesc); // Install shader GLuint program = config->program; glUseProgram(program); // Update and bind transform state struct Transform { float ModelViewMatrix[16]; float ProjectionMatrix[16]; float ModelViewProjectionMatrix[16]; } transformData; setMatrix(mDrawContext.getMatrix(MHWRender::MDrawContext::kWorldViewMtx), transformData.ModelViewMatrix); setMatrix(mDrawContext.getMatrix(MHWRender::MDrawContext::kProjectionMtx), transformData.ProjectionMatrix); setMatrix(mDrawContext.getMatrix(MHWRender::MDrawContext::kWorldViewProjMtx), transformData.ModelViewProjectionMatrix); if (!g_transformUB) { glGenBuffers(1, &g_transformUB); glBindBuffer(GL_UNIFORM_BUFFER, g_transformUB); glBufferData(GL_UNIFORM_BUFFER, sizeof(transformData), NULL, GL_STATIC_DRAW); }; glBindBuffer(GL_UNIFORM_BUFFER, g_transformUB); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(transformData), &transformData); glBindBuffer(GL_UNIFORM_BUFFER, 0); glBindBufferBase(GL_UNIFORM_BUFFER, g_transformBinding, g_transformUB); // Update and bind tessellation state struct Tessellation { float TessLevel; int GregoryQuadOffsetBase; int PrimitiveIdBase; } tessellationData; tessellationData.TessLevel = static_cast<float>(1 << _tessFactor); tessellationData.GregoryQuadOffsetBase = patch.GetQuadOffsetBase; tessellationData.PrimitiveIdBase = patch.GetPatchIndex();; if (!g_tessellationUB) { glGenBuffers(1, &g_tessellationUB); glBindBuffer(GL_UNIFORM_BUFFER, g_tessellationUB); glBufferData(GL_UNIFORM_BUFFER, sizeof(tessellationData), NULL, GL_STATIC_DRAW); }; glBindBuffer(GL_UNIFORM_BUFFER, g_tessellationUB); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(tessellationData), &tessellationData); glBindBuffer(GL_UNIFORM_BUFFER, 0); glBindBufferBase(GL_UNIFORM_BUFFER, g_tessellationBinding, g_tessellationUB); #ifdef USE_NON_IMAGE_BASED_LIGHTING // Update and bind lighting state int numLights = mDrawContext.numberOfActiveLights(); struct Lighting { struct Light { float position[4]; float diffuse[4]; float ambient[4]; float specular[4]; } lightSource[2]; } lightingData; memset(&lightingData, 0, sizeof(lightingData)); for (int i = 0; i < numLights && i < 1; ++i) { MFloatPointArray positions; MFloatVector direction; float intensity; MColor color; bool hasDirection, hasPosition; mDrawContext.getLightInformation(i, positions, direction, intensity, color, hasDirection, hasPosition); Lighting::Light &light = lightingData.lightSource[i]; if (hasDirection) { light.position[0] = -direction[0]; light.position[1] = -direction[1]; light.position[2] = -direction[2]; for (int j = 0; j < 4; ++j) { light.diffuse[j] = color[j] * intensity; light.ambient[j] = color[j] * intensity; light.specular[j] = color[j] * intensity; } } } if (!g_lightingUB) { glGenBuffers(1, &g_lightingUB); glBindBuffer(GL_UNIFORM_BUFFER, g_lightingUB); glBufferData(GL_UNIFORM_BUFFER, sizeof(lightingData), NULL, GL_STATIC_DRAW); }; glBindBuffer(GL_UNIFORM_BUFFER, g_lightingUB); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(lightingData), &lightingData); glBindBuffer(GL_UNIFORM_BUFFER, 0); glBindBufferBase(GL_UNIFORM_BUFFER, g_lightingBinding, g_lightingUB); #endif GLint eye = glGetUniformLocation(program, "eyePositionInWorld"); MPoint e = MPoint(0, 0, 0) * mDrawContext.getMatrix(MHWRender::MDrawContext::kWorldViewInverseMtx); glProgramUniform3f(program, eye, static_cast<float>(e.x), static_cast<float>(e.y), static_cast<float>(e.z)); // update other uniforms float color[4] = { 0, 0, 0, 1 }; _diffuse.get(color); glProgramUniform4fv(program, glGetUniformLocation(program, "diffuseColor"), 1, color); _ambient.get(color); glProgramUniform4fv(program, glGetUniformLocation(program, "ambientColor"), 1, color); _specular.get(color); glProgramUniform4fv(program, glGetUniformLocation(program, "specularColor"), 1, color); glProgramUniform1f(program, glGetUniformLocation(program, "fresnelBias"), _fresnelBias); glProgramUniform1f(program, glGetUniformLocation(program, "fresnelScale"), _fresnelScale); glProgramUniform1f(program, glGetUniformLocation(program, "fresnelPower"), _fresnelPower); // Ptex bindings // color ptex if (effectRegistry.getPtexColorValid()) { GLint texData = glGetUniformLocation(program, "textureImage_Data"); glProgramUniform1i(program, texData, CLR_TEXTURE_UNIT + 0); GLint texPacking = glGetUniformLocation(program, "textureImage_Packing"); glProgramUniform1i(program, texPacking, CLR_TEXTURE_UNIT + 1); GLint texPages = glGetUniformLocation(program, "textureImage_Pages"); glProgramUniform1i(program, texPages, CLR_TEXTURE_UNIT + 2); } // displacement ptex if (effectRegistry.getPtexDisplacementValid()) { GLint texData = glGetUniformLocation(program, "textureDisplace_Data"); glProgramUniform1i(program, texData, DISP_TEXTURE_UNIT + 0); GLint texPacking = glGetUniformLocation(program, "textureDisplace_Packing"); glProgramUniform1i(program, texPacking, DISP_TEXTURE_UNIT + 1); GLint texPages = glGetUniformLocation(program, "textureDisplace_Pages"); glProgramUniform1i(program, texPages, DISP_TEXTURE_UNIT + 2); } // occlusion ptex if (effectRegistry.getPtexOcclusionValid()) { GLint texData = glGetUniformLocation(program, "textureOcclusion_Data"); glProgramUniform1i(program, texData, OCC_TEXTURE_UNIT + 0); GLint texPacking = glGetUniformLocation(program, "textureOcclusion_Packing"); glProgramUniform1i(program, texPacking, OCC_TEXTURE_UNIT + 1); GLint texPages = glGetUniformLocation(program, "textureOcclusion_Pages"); glProgramUniform1i(program, texPages, OCC_TEXTURE_UNIT + 2); } // diffuse environment map if (effectRegistry.getDiffuseEnvironmentId() != 0) { GLint difmap = glGetUniformLocation(program, "diffuseEnvironmentMap"); glProgramUniform1i(program, difmap, DIFF_TEXTURE_UNIT); } // specular environment map if (effectRegistry.getSpecularEnvironmentId() != 0) { GLint envmap = glGetUniformLocation(program, "specularEnvironmentMap"); glProgramUniform1i(program, envmap, ENV_TEXTURE_UNIT); } glActiveTexture(GL_TEXTURE0); CHECK_GL_ERROR("bindProgram leave\n"); return program; }
PXR_NAMESPACE_OPEN_SCOPE /* static */ bool px_vp20Utils::setupLightingGL(const MHWRender::MDrawContext& context) { MStatus status; // Take into account only the 8 lights supported by the basic // OpenGL profile. const unsigned int nbLights = std::min(context.numberOfActiveLights(&status), 8u); if (status != MStatus::kSuccess) return false; if (nbLights > 0) { // Lights are specified in world space and needs to be // converted to view space. glMatrixMode(GL_MODELVIEW); glPushMatrix(); const MMatrix worldToView = context.getMatrix(MHWRender::MDrawContext::kViewMtx, &status); if (status != MStatus::kSuccess) return false; glLoadMatrixd(worldToView.matrix[0]); glEnable(GL_LIGHTING); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); glEnable(GL_COLOR_MATERIAL) ; glEnable(GL_NORMALIZE) ; { const GLfloat ambient[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; const GLfloat specular[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1); } for (unsigned int i=0; i<nbLights; ++i) { MFloatVector direction; float intensity; MColor color; bool hasDirection; bool hasPosition; #if MAYA_API_VERSION >= 201300 // Starting with Maya 2013, getLightInformation() uses MFloatPointArray for positions MFloatPointArray positions; status = context.getLightInformation( i, positions, direction, intensity, color, hasDirection, hasPosition); const MFloatPoint &position = positions[0]; #else // Maya 2012, getLightInformation() uses MFloatPoint for position MFloatPoint position; status = context.getLightInformation( i, position, direction, intensity, color, hasDirection, hasPosition); #endif if (status != MStatus::kSuccess) return false; if (hasDirection) { if (hasPosition) { // Assumes a Maya Spot Light! const GLfloat ambient[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; const GLfloat diffuse[4] = { intensity * color[0], intensity * color[1], intensity * color[2], 1.0f }; const GLfloat pos[4] = { position[0], position[1], position[2], 1.0f }; const GLfloat dir[3] = { direction[0], direction[1], direction[2]}; glLightfv(GL_LIGHT0+i, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0+i, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0+i, GL_POSITION, pos); glLightfv(GL_LIGHT0+i, GL_SPOT_DIRECTION, dir); // Maya's default value's for spot lights. glLightf(GL_LIGHT0+i, GL_SPOT_EXPONENT, 0.0); glLightf(GL_LIGHT0+i, GL_SPOT_CUTOFF, 20.0); } else { // Assumes a Maya Directional Light! const GLfloat ambient[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; const GLfloat diffuse[4] = { intensity * color[0], intensity * color[1], intensity * color[2], 1.0f }; const GLfloat pos[4] = { -direction[0], -direction[1], -direction[2], 0.0f }; glLightfv(GL_LIGHT0+i, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0+i, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0+i, GL_POSITION, pos); glLightf(GL_LIGHT0+i, GL_SPOT_CUTOFF, 180.0); } } else if (hasPosition) { // Assumes a Maya Point Light! const GLfloat ambient[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; const GLfloat diffuse[4] = { intensity * color[0], intensity * color[1], intensity * color[2], 1.0f }; const GLfloat pos[4] = { position[0], position[1], position[2], 1.0f }; glLightfv(GL_LIGHT0+i, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0+i, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0+i, GL_POSITION, pos); glLightf(GL_LIGHT0+i, GL_SPOT_CUTOFF, 180.0); } else { // Assumes a Maya Ambient Light! const GLfloat ambient[4] = { intensity * color[0], intensity * color[1], intensity * color[2], 1.0f }; const GLfloat diffuse[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; const GLfloat pos[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; glLightfv(GL_LIGHT0+i, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0+i, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0+i, GL_POSITION, pos); glLightf(GL_LIGHT0+i, GL_SPOT_CUTOFF, 180.0); } glEnable(GL_LIGHT0+i); } glPopMatrix(); } glDisable(GL_LIGHTING); return nbLights > 0; }