/* From the draw context, get the list of lights and queue the ones we are interested in into the "desired list" */ MStatus shadowPrepass::execute( const MHWRender::MDrawContext & context ) { MHWRender::MRenderer* theRenderer = MHWRender::MRenderer::theRenderer(); if (!theRenderer) return MStatus::kSuccess; // Skip lighting modes where there are no lights which can // cast shadows MHWRender::MDrawContext::LightingMode lightingMode = context.getLightingMode(); if (lightingMode != MHWRender::MDrawContext::kSelectedLights && lightingMode != MHWRender::MDrawContext::kSceneLights) { return MStatus::kSuccess; } MHWRender::MDrawContext::LightFilter lightFilter = MHWRender::MDrawContext::kFilteredIgnoreLightLimit; unsigned int nbSceneLights = context.numberOfActiveLights(lightFilter); for (unsigned int i=0; i<nbSceneLights; i++) { MHWRender::MLightParameterInformation* lightInfo = context.getLightParameterInformation( i, lightFilter ); if (!lightInfo) continue; // Get the actually Maya light node MStatus status = MStatus::kFailure; MDagPath lightPath = lightInfo->lightPath(&status); if (status != MStatus::kSuccess || !lightPath.isValid()) continue; // Would be good to have an API method here to indicate if it // casts shadows MIntArray intVals; // Check if light is enabled, and emits any lighting MHWRender::MLightParameterInformation::StockParameterSemantic semantic = MHWRender::MLightParameterInformation::kLightEnabled; if (MStatus::kSuccess == lightInfo->getParameter( semantic, intVals )) { if (intVals.length()) { if (intVals[0] == 0) continue; } } semantic = MHWRender::MLightParameterInformation::kEmitsDiffuse; if (MStatus::kSuccess == lightInfo->getParameter( semantic, intVals )) { if (intVals.length()) { if (intVals[0] == 0) continue; } } semantic = MHWRender::MLightParameterInformation::kEmitsSpecular; if (MStatus::kSuccess == lightInfo->getParameter( semantic, intVals )) { if (intVals.length()) { if (intVals[0] == 0) continue; } } // Check if local shadows are enabled. semantic = MHWRender::MLightParameterInformation::kShadowOn; if (MStatus::kSuccess == lightInfo->getParameter( semantic, intVals )) { if (intVals.length()) { if (intVals[0] == 0) continue; } } // Check if the shadow is "dirty" bool shadowIsDirty = false; semantic = MHWRender::MLightParameterInformation::kShadowDirty; if (MStatus::kSuccess == lightInfo->getParameter( semantic, intVals )) { if (intVals.length()) { if (intVals[0] == 0) // continue; shadowIsDirty = intVals[0] != 0 ? true : false ; } } // Check the light list to prune, if not already pruned bool prune = false; if (lightingMode != MHWRender::MDrawContext::kSelectedLights) { if (mLightList && mLightList->length()) { prune = !mLightList->hasItem(lightInfo->lightPath()); } } static bool debugShadowRequests = false; // Set that we require shadows for this light if (!prune) { if (debugShadowRequests) fprintf(stderr, "QUEUE light shadows for %s, shadowDirty = %d\n", lightPath.fullPathName().asChar(), shadowIsDirty); theRenderer->setLightRequiresShadows( lightPath.node(), true ); } // Set that we DON'T require shadows for this light else { if (debugShadowRequests) fprintf(stderr, "DEQUEUE light shadows for %s, shadowDirty = %d\n", lightPath.fullPathName().asChar(), shadowIsDirty); theRenderer->setLightRequiresShadows( lightPath.node(), false ); } } return MStatus::kSuccess; }
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; }
/* Utility method to update shader parameters based on available lighting information. */ static void updateLightShader( MHWRender::MShaderInstance *shaderInstance, const MHWRender::MDrawContext & context, const MSelectionList * lightList ) { if (!shaderInstance) return; // Check pass context information to see if we are in a shadow // map update pass. If so do nothing. // const MHWRender::MPassContext & passCtx = context.getPassContext(); const MStringArray & passSem = passCtx.passSemantics(); bool handlePass = true; for (unsigned int i=0; i<passSem.length() && handlePass; i++) { // Handle special pass drawing. // if (passSem[i] == MHWRender::MPassContext::kShadowPassSemantic) { handlePass = false; } } if (!handlePass) return; // // Perform light shader update with lighting information // If the light list is not empty then use that light's information. // Otherwise choose the first appropriate light which can cast shadows. // // Defaults in case there are no lights // bool globalShadowsOn = false; bool localShadowsOn = false; bool shadowDirty = false; MFloatVector direction(0.0f, 0.0f, 1.0f); float lightIntensity = 0.0f; // If no lights then black out the light float lightColor[3] = { 0.0f, 0.0f, 0.0f }; MStatus status; // Scan to find the first N lights that has a direction component in it // It's possible we find no lights. // MHWRender::MDrawContext::LightFilter considerAllSceneLights = MHWRender::MDrawContext::kFilteredIgnoreLightLimit; unsigned int lightCount = context.numberOfActiveLights(considerAllSceneLights); if (lightCount) { MFloatArray floatVals; MIntArray intVals; MHWRender::MTextureAssignment shadowResource; shadowResource.texture = NULL; MHWRender::MSamplerStateDesc samplerDesc; MMatrix shadowViewProj; float shadowColor[3] = { 0.0f, 0.0f, 0.0f }; unsigned int i=0; bool foundDirectional = false; for (i=0; i<lightCount && !foundDirectional ; i++) { MHWRender::MLightParameterInformation *lightParam = context.getLightParameterInformation( i, considerAllSceneLights ); if (lightParam) { // Prune against light list if any. if (lightList && lightList->length()) { if (!lightList->hasItem(lightParam->lightPath())) continue; } MStringArray params; lightParam->parameterList(params); for (unsigned int p=0; p<params.length(); p++) { MString pname = params[p]; MHWRender::MLightParameterInformation::StockParameterSemantic semantic = lightParam->parameterSemantic( pname ); switch (semantic) { // Pick a few light parameters to pick up as an example case MHWRender::MLightParameterInformation::kWorldDirection: lightParam->getParameter( pname, floatVals ); direction = MFloatVector( floatVals[0], floatVals[1], floatVals[2] ); foundDirectional = true; break; case MHWRender::MLightParameterInformation::kIntensity: lightParam->getParameter( pname, floatVals ); lightIntensity = floatVals[0]; break; case MHWRender::MLightParameterInformation::kColor: lightParam->getParameter( pname, floatVals ); lightColor[0] = floatVals[0]; lightColor[1] = floatVals[1]; lightColor[2] = floatVals[2]; break; // Pick up shadowing parameters case MHWRender::MLightParameterInformation::kGlobalShadowOn: lightParam->getParameter( pname, intVals ); if (intVals.length()) globalShadowsOn = (intVals[0] != 0) ? true : false; break; case MHWRender::MLightParameterInformation::kShadowOn: lightParam->getParameter( pname, intVals ); if (intVals.length()) localShadowsOn = (intVals[0] != 0) ? true : false; break; case MHWRender::MLightParameterInformation::kShadowViewProj: lightParam->getParameter( pname, shadowViewProj); break; case MHWRender::MLightParameterInformation::kShadowMap: lightParam->getParameter( pname, shadowResource ); break; case MHWRender::MLightParameterInformation::kShadowDirty: if (intVals.length()) shadowDirty = (intVals[0] != 0) ? true : false; break; case MHWRender::MLightParameterInformation::kShadowSamp: lightParam->getParameter( pname, samplerDesc ); break; case MHWRender::MLightParameterInformation::kShadowColor: lightParam->getParameter( pname, floatVals ); shadowColor[0] = floatVals[0]; shadowColor[1] = floatVals[1]; shadowColor[2] = floatVals[2]; break; default: break; } } /* for params */ } if (foundDirectional && globalShadowsOn && localShadowsOn && shadowResource.texture) { void *resourceHandle = shadowResource.texture->resourceHandle(); if (resourceHandle) { static bool debugShadowBindings = false; status = shaderInstance->setParameter("mayaShadowPCF1_shadowMap", shadowResource ); if (status == MStatus::kSuccess && debugShadowBindings) fprintf(stderr, "Bound shadow map to shader param mayaShadowPCF1_shadowMap\n"); status = shaderInstance->setParameter("mayaShadowPCF1_shadowViewProj", shadowViewProj ); if (status == MStatus::kSuccess && debugShadowBindings) fprintf(stderr, "Bound shadow map transform to shader param mayaShadowPCF1_shadowViewProj\n"); status = shaderInstance->setParameter("mayaShadowPCF1_shadowColor", &shadowColor[0] ); if (status == MStatus::kSuccess && debugShadowBindings) fprintf(stderr, "Bound shadow map color to shader param mayaShadowPCF1_shadowColor\n"); } MHWRender::MRenderer* renderer = MHWRender::MRenderer::theRenderer(); if (renderer) { MHWRender::MTextureManager* textureManager = renderer->getTextureManager(); if (textureManager) { textureManager->releaseTexture(shadowResource.texture); } } shadowResource.texture = NULL; } } } // Set up parameters which should be set regardless of light existence. status = shaderInstance->setParameter("mayaDirectionalLight_direction", &( direction[0] )); status = shaderInstance->setParameter("mayaDirectionalLight_intensity", lightIntensity ); status = shaderInstance->setParameter("mayaDirectionalLight_color", &( lightColor[0] )); status = shaderInstance->setParameter("mayaShadowPCF1_mayaGlobalShadowOn", globalShadowsOn); status = shaderInstance->setParameter("mayaShadowPCF1_mayaShadowOn", localShadowsOn); }
// #### 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; }
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; }
/* static */ GlfSimpleLightingContextRefPtr px_vp20Utils::GetLightingContextFromDrawContext( const MHWRender::MDrawContext& context) { const GfVec4f blackColor(0.0f, 0.0f, 0.0f, 1.0f); const GfVec4f whiteColor(1.0f, 1.0f, 1.0f, 1.0f); GlfSimpleLightingContextRefPtr lightingContext = GlfSimpleLightingContext::New(); MStatus status; unsigned int numMayaLights = context.numberOfActiveLights(MHWRender::MDrawContext::kFilteredToLightLimit, &status); if (status != MS::kSuccess || numMayaLights < 1) { return lightingContext; } bool viewDirectionAlongNegZ = context.viewDirectionAlongNegZ(&status); if (status != MS::kSuccess) { // If we fail to find out the view direction for some reason, assume // that it's along the negative Z axis (OpenGL). viewDirectionAlongNegZ = true; } GlfSimpleLightVector lights; for (unsigned int i = 0; i < numMayaLights; ++i) { MHWRender::MLightParameterInformation* mayaLightParamInfo = context.getLightParameterInformation(i); if (!mayaLightParamInfo) { continue; } // Setup some default values before we read the light parameters. bool lightEnabled = true; bool lightHasPosition = false; GfVec4f lightPosition(0.0f, 0.0f, 0.0f, 1.0f); bool lightHasDirection = false; GfVec3f lightDirection(0.0f, 0.0f, -1.0f); if (!viewDirectionAlongNegZ) { // The convention for DirectX is positive Z. lightDirection[2] = 1.0f; } float lightIntensity = 1.0f; GfVec4f lightColor = blackColor; bool lightEmitsDiffuse = true; bool lightEmitsSpecular = false; float lightDecayRate = 0.0f; float lightDropoff = 0.0f; // The cone angle is 180 degrees by default. GfVec2f lightCosineConeAngle(-1.0f); float lightShadowBias = 0.0f; bool lightShadowOn = false; bool globalShadowOn = false; MStringArray paramNames; mayaLightParamInfo->parameterList(paramNames); for (unsigned int paramIndex = 0; paramIndex < paramNames.length(); ++paramIndex) { const MString paramName = paramNames[paramIndex]; const MHWRender::MLightParameterInformation::ParameterType paramType = mayaLightParamInfo->parameterType(paramName); const MHWRender::MLightParameterInformation::StockParameterSemantic paramSemantic = mayaLightParamInfo->parameterSemantic(paramName); MIntArray intValues; MFloatArray floatValues; switch (paramType) { case MHWRender::MLightParameterInformation::kBoolean: case MHWRender::MLightParameterInformation::kInteger: mayaLightParamInfo->getParameter(paramName, intValues); break; case MHWRender::MLightParameterInformation::kFloat: case MHWRender::MLightParameterInformation::kFloat2: case MHWRender::MLightParameterInformation::kFloat3: case MHWRender::MLightParameterInformation::kFloat4: mayaLightParamInfo->getParameter(paramName, floatValues); break; default: // Unsupported paramType. continue; break; } switch (paramSemantic) { case MHWRender::MLightParameterInformation::kLightEnabled: _GetLightingParam(intValues, floatValues, lightEnabled); break; case MHWRender::MLightParameterInformation::kWorldPosition: if (_GetLightingParam(intValues, floatValues, lightPosition)) { lightHasPosition = true; } break; case MHWRender::MLightParameterInformation::kWorldDirection: if (_GetLightingParam(intValues, floatValues, lightDirection)) { lightHasDirection = true; } break; case MHWRender::MLightParameterInformation::kIntensity: _GetLightingParam(intValues, floatValues, lightIntensity); break; case MHWRender::MLightParameterInformation::kColor: _GetLightingParam(intValues, floatValues, lightColor); break; case MHWRender::MLightParameterInformation::kEmitsDiffuse: _GetLightingParam(intValues, floatValues, lightEmitsDiffuse); break; case MHWRender::MLightParameterInformation::kEmitsSpecular: _GetLightingParam(intValues, floatValues, lightEmitsSpecular); break; case MHWRender::MLightParameterInformation::kDecayRate: _GetLightingParam(intValues, floatValues, lightDecayRate); break; case MHWRender::MLightParameterInformation::kDropoff: _GetLightingParam(intValues, floatValues, lightDropoff); break; case MHWRender::MLightParameterInformation::kCosConeAngle: _GetLightingParam(intValues, floatValues, lightCosineConeAngle); break; case MHWRender::MLightParameterInformation::kShadowBias: _GetLightingParam(intValues, floatValues, lightShadowBias); break; case MHWRender::MLightParameterInformation::kShadowOn: _GetLightingParam(intValues, floatValues, lightShadowOn); break; case MHWRender::MLightParameterInformation::kGlobalShadowOn: _GetLightingParam(intValues, floatValues, globalShadowOn); break; default: // Unsupported paramSemantic. continue; break; } if (!lightEnabled) { // Stop reading light parameters if the light is disabled. break; } } if (!lightEnabled) { // Skip to the next light if this light is disabled. continue; } lightColor[0] *= lightIntensity; lightColor[1] *= lightIntensity; lightColor[2] *= lightIntensity; // Populate a GlfSimpleLight from the light information from Maya. GlfSimpleLight light; GfVec4f lightAmbient = blackColor; GfVec4f lightDiffuse = blackColor; GfVec4f lightSpecular = blackColor; // We receive the cone angle from Maya as a pair of floats which // includes the penumbra, but GlfSimpleLights don't currently support // that, so we only use the primary cone angle value. float lightCutoff = GfRadiansToDegrees(std::acos(lightCosineConeAngle[0])); float lightFalloff = lightDropoff; // decayRate is actually an enum in Maya that we receive as a float: // - 0.0 = no attenuation // - 1.0 = linear attenuation // - 2.0 = quadratic attenuation // - 3.0 = cubic attenuation (not supported by GlfSimpleLight) GfVec3f lightAttenuation(0.0f); if (lightDecayRate > 1.5) { // Quadratic attenuation. lightAttenuation[2] = 1.0f; } else if (lightDecayRate > 0.5f) { // Linear attenuation. lightAttenuation[1] = 1.0f; } else { // No/constant attenuation. lightAttenuation[0] = 1.0f; } if (lightHasDirection && !lightHasPosition) { // This is a directional light. Set the direction as its position. lightPosition[0] = -lightDirection[0]; lightPosition[1] = -lightDirection[1]; lightPosition[2] = -lightDirection[2]; lightPosition[3] = 0.0f; // Revert direction to the default value. lightDirection = GfVec3f(0.0f, 0.0f, -1.0f); if (!viewDirectionAlongNegZ) { lightDirection[2] = 1.0f; } } if (!lightHasPosition && !lightHasDirection) { // This is an ambient light. lightAmbient = lightColor; } else { if (lightEmitsDiffuse) { lightDiffuse = lightColor; } if (lightEmitsSpecular) { // XXX: It seems that the specular color cannot be specified // separately from the diffuse color on Maya lights. lightSpecular = lightColor; } } light.SetAmbient(lightAmbient); light.SetDiffuse(lightDiffuse); light.SetSpecular(lightSpecular); light.SetPosition(lightPosition); light.SetSpotDirection(lightDirection); light.SetSpotCutoff(lightCutoff); light.SetSpotFalloff(lightFalloff); light.SetAttenuation(lightAttenuation); light.SetShadowBias(lightShadowBias); light.SetHasShadow(lightShadowOn && globalShadowOn); lights.push_back(light); } lightingContext->SetLights(lights); // XXX: These material settings match what we used to get when we read the // material from OpenGL. This should probably eventually be something more // sophisticated. GlfSimpleMaterial material; material.SetAmbient(whiteColor); material.SetDiffuse(whiteColor); material.SetSpecular(blackColor); material.SetEmission(blackColor); material.SetShininess(0.0001f); lightingContext->SetMaterial(material); lightingContext->SetSceneAmbient(blackColor); return lightingContext; }
/* static */ void px_vp20Utils::unsetLightingGL(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; // Restore OpenGL default values for anything that we have // modified. if (nbLights > 0) { for (unsigned int i=0; i<nbLights; ++i) { glDisable(GL_LIGHT0+i); const GLfloat ambient[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; glLightfv(GL_LIGHT0+i, GL_AMBIENT, ambient); if (i==0) { const GLfloat diffuse[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; glLightfv(GL_LIGHT0+i, GL_DIFFUSE, diffuse); const GLfloat spec[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; glLightfv(GL_LIGHT0+i, GL_SPECULAR, spec); } else { const GLfloat diffuse[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; glLightfv(GL_LIGHT0+i, GL_DIFFUSE, diffuse); const GLfloat spec[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; glLightfv(GL_LIGHT0+i, GL_SPECULAR, spec); } const GLfloat pos[4] = { 0.0f, 0.0f, 1.0f, 0.0f }; glLightfv(GL_LIGHT0+i, GL_POSITION, pos); const GLfloat dir[3] = { 0.0f, 0.0f, -1.0f }; glLightfv(GL_LIGHT0+i, GL_SPOT_DIRECTION, dir); glLightf(GL_LIGHT0+i, GL_SPOT_EXPONENT, 0.0); glLightf(GL_LIGHT0+i, GL_SPOT_CUTOFF, 180.0); } glDisable(GL_LIGHTING); glDisable(GL_COLOR_MATERIAL) ; glDisable(GL_NORMALIZE) ; const GLfloat ambient[4] = { 0.2f, 0.2f, 0.2f, 1.0f }; const GLfloat specular[4] = { 0.8f, 0.8f, 0.8f, 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, 0); } }