RenderModelExternal & DRAWABLE::generateRenderModelData(StringIdMap & stringMap) { // copy data over to the GL3V renderModel object // eventually this should only be done when we update the values, but for now // we call this every time we draw the drawable // cache off the stringId values static StringId diffuseId = stringMap.addStringId("diffuseTexture"); static StringId misc1Id = stringMap.addStringId("misc1Texture"); static StringId misc2Id = stringMap.addStringId("normalMapTexture"); static StringId transformId = stringMap.addStringId("modelMatrix"); static StringId colorId = stringMap.addStringId("colorTint"); // textures if (texturesChanged) { renderModel.clearTextureCache(); renderModel.textures.clear(); if (diffuse_map && !diffuse_map->IsCube()) // for right now, restrict the diffuse map to 2d textures { renderModel.textures.push_back(RenderTextureEntry(diffuseId, diffuse_map->GetID(), GL_TEXTURE_2D)); } if (misc_map1 && !misc_map1->IsCube()) { renderModel.textures.push_back(RenderTextureEntry(misc1Id, misc_map1->GetID(), GL_TEXTURE_2D)); } if (misc_map2 && !misc_map2->IsCube()) { renderModel.textures.push_back(RenderTextureEntry(misc2Id, misc_map2->GetID(), GL_TEXTURE_2D)); } texturesChanged = false; } // uniforms if (uniformsChanged) { renderModel.clearUniformCache(); renderModel.uniforms.clear(); if (transform != MATRIX4<float>()) // only add it if it's not the identity matrix renderModel.uniforms.push_back(RenderUniformEntry(transformId, transform.GetArray(), 16)); if (r != 1 || g != 1 || b != 1 || a != 1) // only add it if it's not the default { float srgb_alpha[4]; srgb_alpha[0] = r < 1 ? pow(r, 2.2f) : r; srgb_alpha[1] = g < 1 ? pow(g, 2.2f) : g; srgb_alpha[2] = b < 1 ? pow(b, 2.2f) : b; srgb_alpha[3] = a; renderModel.uniforms.push_back(RenderUniformEntry(colorId, srgb_alpha, 4)); } uniformsChanged = false; } return renderModel; }
void GraphicsGL3::SetupScene( float fov, float new_view_distance, const Vec3 cam_position, const Quat & cam_rotation, const Vec3 & /*dynamic_reflection_sample_pos*/, std::ostream & error_output) { lastCameraPosition = cam_position; const float nearDistance = 0.1; setCameraPerspective("default", cam_position, cam_rotation, fov, nearDistance, new_view_distance, w, h); Vec3 skyboxCamPosition(0,0,0); if (fixed_skybox) skyboxCamPosition[2] = cam_position[2]; setCameraPerspective("skybox", skyboxCamPosition, cam_rotation, fov, nearDistance, 10000.f, w, h); // derive light rotation quaternion from light direction vector Quat light_rotation; Vec3 up(0, 0, 1); float cosa = up.dot(light_direction); if (cosa * cosa < 1.0f) { float a = -acosf(cosa); Vec3 x = up.cross(light_direction).Normalize(); light_rotation.SetAxisAngle(a, x[0], x[1], x[2]); } // shadow cameras for (int i = 0; i < 3; i++) { //float shadow_radius = (1<<i)*closeshadow+(i)*20.0; //5,30,60 float shadow_radius = (1<<(2-i))*closeshadow+(2-i)*20.0; Vec3 shadowbox(1,1,1); //shadowbox = shadowbox * (shadow_radius*sqrt(2.0)); shadowbox = shadowbox * (shadow_radius*1.5); Vec3 shadowoffset(0,0,-1); shadowoffset = shadowoffset * shadow_radius; (-cam_rotation).RotateVector(shadowoffset); if (i == 2) shadowbox[2] += 25.0; Vec3 shadowPosition = cam_position+shadowoffset; // snap the shadow camera's location to shadow map texels // this can be commented out to minimize car aliasing at the expense of scenery aliasing const float shadowMapResolution = 512; float snapToGridSize = 2.f*shadowbox[0]/shadowMapResolution; Vec3 cameraSpaceShadowPosition = shadowPosition; light_rotation.RotateVector(cameraSpaceShadowPosition); for (int n = 0; n < 3; n++) { float pos = cameraSpaceShadowPosition[n]; float gridpos = pos / snapToGridSize; gridpos = floor(gridpos); cameraSpaceShadowPosition[n] = gridpos*snapToGridSize; } (-light_rotation).RotateVector(cameraSpaceShadowPosition); shadowPosition = cameraSpaceShadowPosition; std::string suffix = Utils::tostr(i+1); CameraMatrices & shadowcam = setCameraOrthographic("shadow"+suffix, shadowPosition, light_rotation, -shadowbox, shadowbox); std::string matrixName = "shadowMatrix"; // create and send shadow reconstruction matrices // the reconstruction matrix should transform from view to world, then from world to shadow view, then from shadow view to shadow clip space const CameraMatrices & defaultcam = cameras.find("default")->second; Mat4 shadowReconstruction = defaultcam.inverseViewMatrix.Multiply(shadowcam.viewMatrix).Multiply(shadowcam.projectionMatrix); /*//Mat4 shadowReconstruction = shadowcam.projectionMatrix.Multiply(shadowcam.viewMatrix.Multiply(defaultcam.inverseViewMatrix)); std::cout << "shadowcam.projectionMatrix: " << std::endl; shadowcam.projectionMatrix.DebugPrint(std::cout); std::cout << "defaultcam.inverseViewMatrix: " << std::endl; defaultcam.inverseViewMatrix.DebugPrint(std::cout); std::cout << "shadowcam.viewMatrix: " << std::endl; shadowcam.viewMatrix.DebugPrint(std::cout); std::cout << "defaultcam.inverseViewMatrix.Multiply(shadowcam.viewMatrix): " << std::endl; defaultcam.inverseViewMatrix.Multiply(shadowcam.viewMatrix).DebugPrint(std::cout); std::cout << matrixName << ":" << std::endl; shadowReconstruction.DebugPrint(std::cout);*/ //renderer.setGlobalUniform(RenderUniformEntry(stringMap.addStringId(matrixName), shadowReconstruction.GetArray(),16)); // examine the user-defined fields to find out which shadow matrix to send to a pass std::vector <StringId> passes = renderer.getPassNames(); for (std::vector <StringId>::const_iterator i = passes.begin(); i != passes.end(); i++) { std::map <std::string, std::string> fields = renderer.getUserDefinedFields(*i); std::map <std::string, std::string>::const_iterator field = fields.find(matrixName); if (field != fields.end() && field->second == suffix) { renderer.setPassUniform(*i, RenderUniformEntry(stringMap.addStringId(matrixName), shadowReconstruction.GetArray(),16)); } } } // send cameras to passes for (std::map <std::string, std::string>::const_iterator i = passNameToCameraName.begin(); i != passNameToCameraName.end(); i++) { renderer.setPassUniform(stringMap.addStringId(i->first), RenderUniformEntry(stringMap.addStringId("viewMatrix"), cameras[i->second].viewMatrix.GetArray(),16)); renderer.setPassUniform(stringMap.addStringId(i->first), RenderUniformEntry(stringMap.addStringId("projectionMatrix"), cameras[i->second].projectionMatrix.GetArray(),16)); } // send matrices for the default camera const CameraMatrices & defaultCamera = cameras.find("default")->second; renderer.setGlobalUniform(RenderUniformEntry(stringMap.addStringId("invProjectionMatrix"), defaultCamera.inverseProjectionMatrix.GetArray(),16)); renderer.setGlobalUniform(RenderUniformEntry(stringMap.addStringId("invViewMatrix"), defaultCamera.inverseViewMatrix.GetArray(),16)); renderer.setGlobalUniform(RenderUniformEntry(stringMap.addStringId("defaultViewMatrix"), defaultCamera.viewMatrix.GetArray(),16)); renderer.setGlobalUniform(RenderUniformEntry(stringMap.addStringId("defaultProjectionMatrix"), defaultCamera.projectionMatrix.GetArray(),16)); // send sun light direction for the default camera // transform to eyespace (view space) MathVector <float, 4> lightDirection4; for (int i = 0; i < 3; i++) lightDirection4[i] = light_direction[i]; lightDirection4[3] = 0; defaultCamera.viewMatrix.MultiplyVector4(&lightDirection4[0]); // upload to the shaders RenderUniformEntry lightDirectionUniform(stringMap.addStringId("eyespaceLightDirection"), &lightDirection4[0], 3); renderer.setGlobalUniform(lightDirectionUniform); // set the reflection strength // TODO: read this from the track definition float reflectedLightColor[4]; for (int i = 0; i < 3; i++) reflectedLightColor[i] = 0.5; reflectedLightColor[3] = 1.; renderer.setGlobalUniform(RenderUniformEntry(stringMap.addStringId("reflectedLightColor"), reflectedLightColor, 4)); // set the ambient strength // TODO: read this from the track definition float ambientLightColor[4]; for (int i = 0; i < 3; i++) ambientLightColor[i] = 1.56; ambientLightColor[3] = 1.; renderer.setGlobalUniform(RenderUniformEntry(stringMap.addStringId("ambientLightColor"), ambientLightColor, 4)); // set the sun strength // TODO: read this from the track definition float directionalLightColor[4]; for (int i = 0; i < 3; i++) directionalLightColor[i] = 8.3; directionalLightColor[3] = 1.; renderer.setGlobalUniform(RenderUniformEntry(stringMap.addStringId("directionalLightColor"), directionalLightColor, 4)); AssembleDrawMap(error_output); }