private ColorRGBA getAmbientColor(LightList lightList) { ambientLightColor.set(0, 0, 0, 1); for (int j = 0; j < lightList.size(); j++) { Light l = lightList.get(j); if (l instanceof AmbientLight) { ambientLightColor.addLocal(l.getColor()); } } ambientLightColor.a = 1.0f; return ambientLightColor; }
protected void renderMultipassLighting(Shader shader, Geometry g, RenderManager rm) { Renderer r = rm.getRenderer(); LightList lightList = g.getWorldLightList(); Uniform lightDir = shader.getUniform("g_LightDirection"); Uniform lightColor = shader.getUniform("g_LightColor"); Uniform lightPos = shader.getUniform("g_LightPosition"); Uniform ambientColor = shader.getUniform("g_AmbientLightColor"); boolean isFirstLight = true; boolean isSecondLight = false; for (int i = 0; i < lightList.size(); i++) { Light l = lightList.get(i); if (l instanceof AmbientLight) { continue; } if (isFirstLight) { // set ambient color for first light only ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList)); isFirstLight = false; isSecondLight = true; } else if (isSecondLight) { ambientColor.setValue(VarType.Vector4, ColorRGBA.Black); // apply additive blending for 2nd and future lights r.applyRenderState(additiveLight); isSecondLight = false; } TempVars vars = TempVars.get(); Quaternion tmpLightDirection = vars.quat1; Quaternion tmpLightPosition = vars.quat2; ColorRGBA tmpLightColor = vars.color; Vector4f tmpVec = vars.vect4f; ColorRGBA color = l.getColor(); tmpLightColor.set(color); tmpLightColor.a = l.getType().getId(); lightColor.setValue(VarType.Vector4, tmpLightColor); switch (l.getType()) { case Directional: DirectionalLight dl = (DirectionalLight) l; Vector3f dir = dl.getDirection(); tmpLightPosition.set(dir.getX(), dir.getY(), dir.getZ(), -1); lightPos.setValue(VarType.Vector4, tmpLightPosition); tmpLightDirection.set(0, 0, 0, 0); lightDir.setValue(VarType.Vector4, tmpLightDirection); break; case Point: PointLight pl = (PointLight) l; Vector3f pos = pl.getPosition(); float invRadius = pl.getInvRadius(); tmpLightPosition.set(pos.getX(), pos.getY(), pos.getZ(), invRadius); lightPos.setValue(VarType.Vector4, tmpLightPosition); tmpLightDirection.set(0, 0, 0, 0); lightDir.setValue(VarType.Vector4, tmpLightDirection); break; case Spot: SpotLight sl = (SpotLight) l; Vector3f pos2 = sl.getPosition(); Vector3f dir2 = sl.getDirection(); float invRange = sl.getInvSpotRange(); float spotAngleCos = sl.getPackedAngleCos(); tmpLightPosition.set(pos2.getX(), pos2.getY(), pos2.getZ(), invRange); lightPos.setValue(VarType.Vector4, tmpLightPosition); // We transform the spot directoin in view space here to save 5 varying later in the // lighting shader // one vec4 less and a vec4 that becomes a vec3 // the downside is that spotAngleCos decoding happen now in the frag shader. tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(), 0); rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); tmpLightDirection.set(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos); lightDir.setValue(VarType.Vector4, tmpLightDirection); break; default: throw new UnsupportedOperationException("Unknown type of light: " + l.getType()); } vars.release(); r.setShader(shader); r.renderMesh(g.getMesh(), g.getLodLevel(), 1); } if (isFirstLight && lightList.size() > 0) { // There are only ambient lights in the scene. Render // a dummy "normal light" so we can see the ambient ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList)); lightColor.setValue(VarType.Vector4, ColorRGBA.BlackNoAlpha); lightPos.setValue(VarType.Vector4, nullDirLight); r.setShader(shader); r.renderMesh(g.getMesh(), g.getLodLevel(), 1); } }
/** * Uploads the lights in the light list as two uniform arrays.<br> * <br> * * * * <p><code>uniform vec4 g_LightColor[numLights];</code><br> * // g_LightColor.rgb is the diffuse/specular color of the light.<br> * // g_Lightcolor.a is the type of light, 0 = Directional, 1 = Point, <br> * // 2 = Spot. <br> * <br> * <code>uniform vec4 g_LightPosition[numLights];</code><br> * // g_LightPosition.xyz is the position of the light (for point lights)<br> * // or the direction of the light (for directional lights).<br> * // g_LightPosition.w is the inverse radius (1/r) of the light (for attenuation) <br> */ protected void updateLightListUniforms(Shader shader, Geometry g, int numLights) { if (numLights == 0) { // this shader does not do lighting, ignore. return; } LightList lightList = g.getWorldLightList(); Uniform lightColor = shader.getUniform("g_LightColor"); Uniform lightPos = shader.getUniform("g_LightPosition"); Uniform lightDir = shader.getUniform("g_LightDirection"); lightColor.setVector4Length(numLights); lightPos.setVector4Length(numLights); lightDir.setVector4Length(numLights); Uniform ambientColor = shader.getUniform("g_AmbientLightColor"); ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList)); int lightIndex = 0; for (int i = 0; i < numLights; i++) { if (lightList.size() <= i) { lightColor.setVector4InArray(0f, 0f, 0f, 0f, lightIndex); lightPos.setVector4InArray(0f, 0f, 0f, 0f, lightIndex); } else { Light l = lightList.get(i); ColorRGBA color = l.getColor(); lightColor.setVector4InArray( color.getRed(), color.getGreen(), color.getBlue(), l.getType().getId(), i); switch (l.getType()) { case Directional: DirectionalLight dl = (DirectionalLight) l; Vector3f dir = dl.getDirection(); lightPos.setVector4InArray(dir.getX(), dir.getY(), dir.getZ(), -1, lightIndex); break; case Point: PointLight pl = (PointLight) l; Vector3f pos = pl.getPosition(); float invRadius = pl.getInvRadius(); lightPos.setVector4InArray(pos.getX(), pos.getY(), pos.getZ(), invRadius, lightIndex); break; case Spot: SpotLight sl = (SpotLight) l; Vector3f pos2 = sl.getPosition(); Vector3f dir2 = sl.getDirection(); float invRange = sl.getInvSpotRange(); float spotAngleCos = sl.getPackedAngleCos(); lightPos.setVector4InArray(pos2.getX(), pos2.getY(), pos2.getZ(), invRange, lightIndex); lightDir.setVector4InArray( dir2.getX(), dir2.getY(), dir2.getZ(), spotAngleCos, lightIndex); break; case Ambient: // skip this light. Does not increase lightIndex continue; default: throw new UnsupportedOperationException("Unknown type of light: " + l.getType()); } } lightIndex++; } while (lightIndex < numLights) { lightColor.setVector4InArray(0f, 0f, 0f, 0f, lightIndex); lightPos.setVector4InArray(0f, 0f, 0f, 0f, lightIndex); lightIndex++; } }