📄 graytrace.cpp
字号:
if(pDistance) m_pBoundingBoxTree->FindClosestIntersection(m_pCamera->GetLookFromPoint(), &directionVector, pDistance); return pRay->m_color.GetGColor();}#define SQRT_RAYS_PER_PIXEL 12GColor GRayTraceScene::RenderPixelAntiAliassed(GRayTraceRay* pRay, GRayTraceVector* pScreenPoint, GRayTraceReal* pDistance){ GRayTraceVector jitter; int x, y; GRayTraceColor col; GRayTraceReal focalDistance = m_pCamera->GetFocalDistance(); GRayTraceReal r1, r2; for(y = 0; y < SQRT_RAYS_PER_PIXEL; y++) { for(x = 0; x < SQRT_RAYS_PER_PIXEL; x++) { GRayTraceVector directionVector(pScreenPoint); // Jitter in X direction jitter.Copy(&m_pixDX); jitter.Multiply((GRayTraceReal)(((double)x + GBits::GetRandomDouble()) / SQRT_RAYS_PER_PIXEL - .5)); directionVector.Add(&jitter); // Jitter in Y direction jitter.Copy(&m_pixDY); jitter.Multiply((GRayTraceReal)(((double)y + GBits::GetRandomDouble()) / SQRT_RAYS_PER_PIXEL - .5)); directionVector.Add(&jitter); // Cast the ray directionVector.Subtract(m_pCamera->GetLookFromPoint()); if(focalDistance > 0) { // Use focus lens -- Start from a random point on the lens and fire at the focal point while(true) { r1 = (GRayTraceReal)(GBits::GetRandomDouble() - .5); r2 = (GRayTraceReal)(GBits::GetRandomDouble() - .5); if(r1 * r1 + r2 * r2 <= .25) break; } GRayTraceVector dx(m_pCamera->GetViewSideVector()); dx.Multiply(r1 * m_pCamera->GetLensDiameter()); GRayTraceVector dy(m_pCamera->GetViewUpVector()); dy.Multiply(r2 * m_pCamera->GetLensDiameter()); directionVector.Multiply(focalDistance); directionVector.Subtract(&dx); directionVector.Subtract(&dy); directionVector.Normalize(); GRayTraceVector lensPoint(m_pCamera->GetLookFromPoint()); lensPoint.Add(&dx); lensPoint.Add(&dy); pRay->Cast(this, &lensPoint, &directionVector, m_pCamera->GetMaxDepth()); } else { // Perfect focus -- just fire straight directionVector.Normalize(); pRay->Cast(this, m_pCamera->GetLookFromPoint(), &directionVector, m_pCamera->GetMaxDepth()); } // Make sure the color doesn't exceed pure white since it will be added with other measurements pRay->m_color.Clip(); col.Add(&pRay->m_color); } } col.Multiply((GRayTraceReal)1 / (SQRT_RAYS_PER_PIXEL * SQRT_RAYS_PER_PIXEL)); if(pDistance) { GRayTraceVector directionVector(pScreenPoint); directionVector.Subtract(m_pCamera->GetLookFromPoint()); directionVector.Normalize(); m_pBoundingBoxTree->FindClosestIntersection(m_pCamera->GetLookFromPoint(), &directionVector, pDistance); } return col.GetGColor();}GColor GRayTraceScene::RenderPixelPathTrace(GRayTraceRay* pRay, GRayTraceVector* pScreenPoint){ GRayTraceVector jitter; int x, y; GRayTraceColor col; GRayTraceReal focalDistance = m_pCamera->GetFocalDistance(); GRayTraceReal r1, r2; for(y = 0; y < SQRT_RAYS_PER_PIXEL; y++) { for(x = 0; x < SQRT_RAYS_PER_PIXEL; x++) { GRayTraceVector directionVector(pScreenPoint); // Jitter in X direction jitter.Copy(&m_pixDX); jitter.Multiply((GRayTraceReal)(((double)x + GBits::GetRandomDouble()) / SQRT_RAYS_PER_PIXEL - .5)); directionVector.Add(&jitter); // Jitter in Y direction jitter.Copy(&m_pixDY); jitter.Multiply((GRayTraceReal)(((double)y + GBits::GetRandomDouble()) / SQRT_RAYS_PER_PIXEL - .5)); directionVector.Add(&jitter); // Cast the ray directionVector.Subtract(m_pCamera->GetLookFromPoint()); if(focalDistance > 0) { // Use focus lens -- Start from a random point on the lens and fire at the focal point while(true) { r1 = (GRayTraceReal)(GBits::GetRandomDouble() - .5); r2 = (GRayTraceReal)(GBits::GetRandomDouble() - .5); if(r1 * r1 + r2 * r2 <= .25) break; } GRayTraceVector dx(m_pCamera->GetViewSideVector()); dx.Multiply(r1 * m_pCamera->GetLensDiameter()); GRayTraceVector dy(m_pCamera->GetViewUpVector()); dy.Multiply(r2 * m_pCamera->GetLensDiameter()); directionVector.Multiply(focalDistance); directionVector.Subtract(&dx); directionVector.Subtract(&dy); directionVector.Normalize(); GRayTraceVector lensPoint(m_pCamera->GetLookFromPoint()); lensPoint.Add(&dx); lensPoint.Add(&dy); pRay->Trace(this, &lensPoint, &directionVector, m_pCamera->GetMaxDepth(), true); } else { // Perfect focus -- just fire straight directionVector.Normalize(); pRay->Trace(this, m_pCamera->GetLookFromPoint(), &directionVector, m_pCamera->GetMaxDepth(), true); } col.Add(&pRay->m_color); } } col.Multiply((GRayTraceReal)1 / (SQRT_RAYS_PER_PIXEL * SQRT_RAYS_PER_PIXEL)); // Apply tone mapping constant GRayTraceReal luminance = col.r * (GRayTraceReal)0.299 + col.g * (GRayTraceReal)0.587 + col.b * (GRayTraceReal)0.114; GRayTraceReal desiredLuminance = (m_toneMappingConstant * luminance) / ((GRayTraceReal)1.0 + m_toneMappingConstant * luminance); col.Multiply(desiredLuminance / luminance); return col.GetGColor();}bool GRayTraceScene::RenderLine(){ if(m_nY < 0) return false; GRayTraceRay ray; int x; GRayTraceVector screenPoint(&m_pixSide); screenPoint.Copy(&m_pixSide); m_pixSide.Add(&m_pixDY); int nWidth = m_pImage->GetWidth(); GRayTraceReal distance; GRayTraceReal* pDistance = m_pDistanceMap ? &distance : NULL; GColor col = 0; for(x = nWidth - 1; x >= 0; x--) { switch(m_eMode) { case FAST_RAY_TRACE: col = RenderPixel(&ray, &screenPoint, pDistance); break; case QUALITY_RAY_TRACE: col = RenderPixelAntiAliassed(&ray, &screenPoint, pDistance); break; case PATH_TRACE: col = RenderPixelPathTrace(&ray, &screenPoint); break; default: GAssert(false, "unrecognized case"); } m_pImage->SetPixel(x, m_nY, col); if(pDistance) m_pDistanceMap[nWidth * m_nY + x] = distance; screenPoint.Add(&m_pixDX); } if(--m_nY >= 0) return true; else return false;}void GRayTraceScene::Render(){ RenderBegin(); while(RenderLine()) { }}GColor GRayTraceScene::RenderSinglePixel(int x, int y){ // Init the rendering RenderBegin(); // Compute the screen point GRayTraceVector screenPoint(&m_pixSide); m_pixDY.Multiply((GRayTraceReal)(m_pImage->GetHeight() - 1 - y)); screenPoint.Add(&m_pixDY); m_pixDX.Multiply((GRayTraceReal)(m_pImage->GetWidth() - 1 - x)); screenPoint.Add(&m_pixDX); // Cast the ray GRayTraceRay ray; GColor c = RenderPixel(&ray, &screenPoint, NULL); return c;}// -----------------------------------------------------------------------------GRayTraceLight::GRayTraceLight(GRayTraceReal r, GRayTraceReal g, GRayTraceReal b): m_color(1, r, g, b){}/*virtual*/ GRayTraceLight::~GRayTraceLight(){}// -----------------------------------------------------------------------------GRayTraceDirectionalLight::GRayTraceDirectionalLight(GRayTraceReal dx, GRayTraceReal dy, GRayTraceReal dz, GRayTraceReal r, GRayTraceReal g, GRayTraceReal b, GRayTraceReal jitter): GRayTraceLight(r, g, b), m_direction(dx, dy, dz), m_jitter(jitter){}/*virtual*/ GRayTraceDirectionalLight::~GRayTraceDirectionalLight(){}/*virtual*/ void GRayTraceDirectionalLight::ComputeColorContribution(GRayTraceScene* pScene, GRayTraceRay* pRay, GRayTraceMaterial* pMaterial, bool bSpecular){ GRayTraceVector direction(&m_direction); if(m_jitter > 0) GRayTraceRay::JitterRay(&direction, m_jitter); // Check if the point is in a shadow GRayTraceReal distance; if(pScene->GetBoundingBoxTree()->FindClosestIntersection(&pRay->m_collisionPoint, &direction, &distance)) return; // Compute diffuse component of the color GRayTraceColor diffuse(pMaterial->GetColor(GRayTraceMaterial::Diffuse, pRay)); diffuse.Multiply(MAX((GRayTraceReal)0, direction.DotProduct(&pRay->m_normalVector))); // Compute specular component of the color if(bSpecular) { GRayTraceReal mag = (GRayTraceReal)pow(MAX((GRayTraceReal)0, pRay->m_reflectionVector.DotProduct(&direction)), pMaterial->GetSpecularExponent()); GRayTraceColor specular(pMaterial->GetColor(GRayTraceMaterial::Specular, pRay)); specular.Multiply(mag); diffuse.Add(&specular); } // Multiply by light intensity diffuse.Multiply(&m_color); pRay->m_color.Add(&diffuse);}// -----------------------------------------------------------------------------GRayTracePointLight::GRayTracePointLight(GRayTraceReal x, GRayTraceReal y, GRayTraceReal z, GRayTraceReal r, GRayTraceReal g, GRayTraceReal b, GRayTraceReal jitter): GRayTraceLight(r, g, b), m_position(x, y, z), m_jitter(jitter){}/*virtual*/ GRayTracePointLight::~GRayTracePointLight(){}/*virtual*/ void GRayTracePointLight::ComputeColorContribution(GRayTraceScene* pScene, GRayTraceRay* pRay, GRayTraceMaterial* pMaterial, bool bSpecular){ GRayTraceVector lightDirection(&m_position); if(m_jitter > 0) { // Jitter light position (to create soft shadows) lightDirection.m_vals[0] += (GRayTraceReal)(m_jitter * 2 * GBits::GetRandomDouble() - m_jitter); lightDirection.m_vals[1] += (GRayTraceReal)(m_jitter * 2 * GBits::GetRandomDouble() - m_jitter); lightDirection.m_vals[2] += (GRayTraceReal)(m_jitter * 2 * GBits::GetRandomDouble() - m_jitter); } // Check if the point is in a shadow lightDirection.Subtract(&pRay->m_collisionPoint); double distsqared = lightDirection.GetMagnitudeSquared(); lightDirection.Normalize(); GRayTraceReal distance; if(pScene->GetBoundingBoxTree()->FindClosestIntersection(&pRay->m_collisionPoint, &lightDirection, &distance)) { if(distance * distance < distsqared) return; } // Compute diffuse component of the color GRayTraceColor diffuse(pMaterial->GetColor(GRayTraceMaterial::Diffuse, pRay)); diffuse.Multiply(MAX((GRayTraceReal)0, lightDirection.DotProduct(&pRay->m_normalVector))); // Compute specular component of the color if(bSpecular) { GRayTraceReal mag = (GRayTraceReal)pow(MAX((GRayTraceReal)0, pRay->m_reflectionVector.DotProduct(&lightDirection)), pMaterial->GetSpecularExponent()); GRayTraceColor specular(pMaterial->GetColor(GRayTraceMaterial::Specular, pRay)); specular.Multiply(mag); diffuse.Add(&specular); } // Multiply by light intensity diffuse.Multiply(&m_color); diffuse.Multiply((GRayTraceReal)(1.0 / distsqared)); pRay->m_color.Add(&diffuse);}// -----------------------------------------------------------------------------GRayTraceAreaLight::GRayTraceAreaLight(GRayTraceObject* pObject, GRayTraceReal r, GRayTraceReal g, GRayTraceReal b): GRayTraceLight(r, g, b), m_pObject(pObject){}/*virtual*/ GRayTraceAreaLight::~GRayTraceAreaLight(){}/*virtual*/ void GRayTraceAreaLight::ComputeColorContribution(GRayTraceScene* pScene, GRayTraceRay* pRay, GRayTraceMaterial* pMaterial, bool bSpecular){ GRayTraceVector lightDirection; if(m_pObject->GetType() == GRayTraceObject::Triangle) { // Pick a random point on the triangle GRayTraceTriangle* pTri = (GRayTraceTriangle*)m_pObject; GRayTraceVector u(pTri->GetVertex(1)); u.Subtract(pTri->GetVertex(0)); GRayTraceVector v(pTri->GetVertex(2)); v.Subtract(pTri->GetVertex(0)); double a = GBits::GetRandomDouble() * 2 - 1; double b = GBits::GetRandomDouble() * 2 - 1; if(a + b > 1) { a = 1 - a; b = 1 - b; } u.Multiply((GRayTraceReal)a); v.Multiply((GRayTraceReal)b); lightDirection.Copy(pTri->GetVertex(0)); lightDirection.Add(&u); lightDirection.Add(&v); } else if(m_pObject->GetType() == GRayTraceObject::Sphere) { // Pick a random point on a disc facing the point of collision GRayTraceSphere* pSphere = (GRayTraceSphere*)m_pObject; GRayTraceVector u, v; GRayTraceVector N(pSphere->GetCenter()); N.Subtract(&pRay->m_collisionPoint); N.Normalize(); if(ABS(N.m_vals[0]) < 0.5) { v.m_vals[0] = 1; u.CrossProduct(&N, &v); } else { v.m_vals[1] = 1; u.CrossProduct(&N, &v); } u.Normalize(); v.CrossProduct(&u, &N); double a, b; while(true) { a = GBits::GetRandomDouble() * 2 - 1; b = GBits::GetRandomDouble() * 2 - 1; if(a * a + b * b < 1) break; } u.Multiply((GRayTraceReal)a); v.Multiply((GRayTraceReal)b); lightDirection.Copy(pSphere->GetCenter()); lightDirection.Add(&u); lightDirection.Add(&v); } else { GAssert(false, "Unrecognized object type"); } // Check if the point is in a shadow lightDirection.Subtract(&pRay->m_collisionPoint); double distsqared = lightDirection.GetMagnitudeSquared(); lightDirection.Normalize(); GRayTraceReal distance; GRayTraceObject* pObj = pScene->GetBoundingBoxTree()->FindClosestIntersection(&pRay->m_collisionPoint, &lightDirection, &distance); if(pObj != m_pObject && pObj && distance * distance < distsqared) return; GRayTraceColor diffuse(&m_color); diffuse.Multiply(pMaterial->GetColor(GRayTraceMaterial::Diffuse, pRay)); if(m_pObject->GetType() == GRayTraceObject::Triangle) { GRayTraceTriangle* pTri = (GRayTraceTriangle*)m_pObject; GRayTraceVector u(pTri->GetVertex(1)); u.Subtract(pTri->GetVertex(0)); GRayTraceVector v(pTri->GetVertex(2)); v.Subtract(pTri->GetVertex(0)); GRayTraceVector t; t.CrossProduct(&u, &v); GRayTraceReal triangleArea = (GRayTraceReal)sqrt(t.GetMagnitudeSquared()) / 2; GRayTraceVector triangleNormal; triangleNormal.ComputeTriangleNormal(pTri->GetVertex(0), pTri->GetVertex(1), pTri->GetVertex(2)); diffuse.Multiply(ABS(pRay->m_normalVector.DotProduct(&lightDirection) * triangleNormal.DotProduct(&lightDirection) * triangleArea / (GRayTraceReal)(PI * distsqared))); } else { GRayTraceSphere* pSphere = (GRayTraceSphere*)m_pObject; diffuse.Multiply(pRay->m_normalVector.DotProduct(&lightDirection) * pSphere->GetRadius() * pSphere->GetRadius() / (GRayTraceReal)distsqared); } pRay->m_color.Add(&diffuse);}// -----------------------------------------------------------------------------GRayTraceMaterial::GRayTraceMaterial(){ SetColor(Diffuse, (GRayTraceReal).5, (GRayTraceReal).5, (GRayTraceReal).5); SetColor(Specular, 1, 1, 1); SetColor(Reflective, 1, 1, 1); SetColor(Transmissive, 0, 0, 0); SetColor(Ambient, (GRayTraceReal).1, (GRayTraceReal).1, (GRayTraceReal).1); SetColor(Emissive, 0, 0, 0); m_indexOfRefraction = 1; m_specularExponent = 1; m_glossiness = 0; m_cloudiness = 0; m_pTextureImage = NULL; m_bDeleteTextureImage = false;}GRayTraceMaterial::GRayTraceMaterial(GRayTraceMaterial* pThat){ SetColor(Diffuse, pThat->GetColor(Diffuse, NULL)); SetColor(Specular, pThat->GetColor(Specular, NULL)); SetColor(Reflective, pThat->GetColor(Reflective, NULL)); SetColor(Transmissive, pThat->GetColor(Transmissive, NULL)); SetColor(Ambient, pThat->GetColor(Ambient, NULL)); SetColor(Emissive, pThat->GetColor(Emissive, NULL)); m_indexOfRefraction = pThat->m_indexOfRefraction; m_specularExponent = pThat->m_specularExponent; m_glossiness = pThat->m_glossiness; m_cloudiness = pThat->m_cloudiness; m_pTextureImage = pThat->m_pTextureImage; m_bDeleteTextureImage = false;}GRayTraceMaterial::~GRayTraceMaterial(){ if(m_bDeleteTextureImage) delete(m_pTextureImage);}GRayTraceColor* GRayTraceMaterial::GetColor(ColorType eType, GRayTraceRay* pRay){ if(m_pTextureImage && eType == Diffuse) { GAssert(pRay->DidRayHitTexture(), "ray doesn't know about this");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -