From 15740faf9fe9fe4be08965098bbf2947e096aeeb Mon Sep 17 00:00:00 2001 From: chai Date: Wed, 14 Aug 2019 22:50:43 +0800 Subject: +Unity Runtime code --- Runtime/Camera/Skybox.cpp | 199 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 Runtime/Camera/Skybox.cpp (limited to 'Runtime/Camera/Skybox.cpp') diff --git a/Runtime/Camera/Skybox.cpp b/Runtime/Camera/Skybox.cpp new file mode 100644 index 0000000..528859e --- /dev/null +++ b/Runtime/Camera/Skybox.cpp @@ -0,0 +1,199 @@ +#include "UnityPrefix.h" +#include "Skybox.h" +#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h" +#include "Camera.h" +#include "CameraUtil.h" +#include "Runtime/Shaders/Material.h" +#include "External/shaderlab/Library/intshader.h" +#include "Runtime/Shaders/Shader.h" +#include "Runtime/GfxDevice/GfxDevice.h" +#include "Runtime/Shaders/VBO.h" +#include "Runtime/Profiler/ExternalGraphicsProfiler.h" + +PROFILER_INFORMATION(gRenderSkyboxProfile, "Camera.RenderSkybox", kProfilerRender); + + +using namespace ShaderLab; + +enum +{ + kSkyboxVertexChannels = (1<GetShader(); + Assert (shader); + + GfxDevice& device = GetGfxDevice(); + + DeviceMVPMatricesState preserveMVP; + + #if UNITY_WP8 + void RotateScreenIfNeeded(Matrix4x4f& mat); + #endif + + if (camera.GetOrthographic()) + { + const float epsilon = 1e-6f; + const float nearPlane = camera.GetNear () * 0.01f; + const float dist = camera.GetFar() * 10.0f; + + // Make Ortho matrix which passes W to Z + Matrix4x4f projection = Matrix4x4f::identity; + //camera.GetImplicitProjectionMatrix( nearPlane, projection ); + projection.Get(2, 2) = -1.0f + epsilon; + projection.Get(2, 3) = (-2.0f + epsilon) * nearPlane; + projection.Get(3, 2) = -1.0f; + + #if UNITY_WP8 + if (!RenderTexture::GetActive()) { + RotateScreenIfNeeded(projection); + } + #endif + + Matrix4x4f matrix = Matrix4x4f::identity; + //device.SetViewMatrix(matrix.GetPtr()); + matrix.SetScale(Vector3f(dist,dist,dist)); + matrix.SetPosition( camera.GetPosition() ); + device.SetWorldMatrix(matrix.GetPtr()); + device.SetProjectionMatrix(projection); + } + else + { + // Modify Projection matrix to make Infinite Projection Matrix (which passes W into Z) + // perspective divide will lend ZBuffer value to always be 1.0 (all points on far plane) + // NOTE: However we need to compensate on floating point precision errors + // by bringing Z slightly closer to viewer by adding Epsilon + // See "Projection Matrix Tricks" by Eric Lengyel GDC2007 + // http://www.terathon.com/gdc07_lengyel.ppt + + // In order to avoid clipping of skybox polys we increase skybox size and pull NearPlane as close as possible + // Higher epsilon values that Z/W < 1.0, but drastically reduces zBuffer precision close to FarPlane + // Epsilon 1e-6 gives good results as long as NearPlane >= 0.05 + const float epsilon = 1e-6f; + const float nearPlane = camera.GetNear () * 0.01f; + const float dist = camera.GetFar() * 10.0f; + + Matrix4x4f projection; + camera.GetImplicitProjectionMatrix( nearPlane, projection ); + projection.Get(2, 2) = -1.0f + epsilon; + projection.Get(2, 3) = (-2.0f + epsilon) * nearPlane; + projection.Get(3, 2) = -1.0f; + + #if UNITY_WP8 + if (!RenderTexture::GetActive()) { + RotateScreenIfNeeded(projection); + } + #endif + + Matrix4x4f matrix = Matrix4x4f::identity; + matrix.SetScale( Vector3f(dist,dist,dist) ); + matrix.SetPosition( camera.GetPosition() ); + device.SetWorldMatrix( matrix.GetPtr() ); + device.SetProjectionMatrix(projection); + } + + ShaderLab::IntShader* slshader = shader->GetShaderLabShader(); + const int passCount = slshader->GetActiveSubShader().GetValidPassCount(); + if( passCount == 6 ) + { + // regular skybox with 6 separate textures per face + DynamicVBO& vbo = device.GetDynamicVBO(); + for( int j = 0; j < 6; j++ ) + { + SkyboxVertex* vbPtr = 0; + if(vbo.GetChunk(kSkyboxVertexChannels, 4, 0, DynamicVBO::kDrawQuads, (void**)&vbPtr, NULL)) + { + vbPtr[0] = kSkyboxVB[4*j+0]; + vbPtr[1] = kSkyboxVB[4*j+1]; + vbPtr[2] = kSkyboxVB[4*j+2]; + vbPtr[3] = kSkyboxVB[4*j+3]; + + vbo.ReleaseChunk(4, 0); + + const ChannelAssigns* channels = mat->SetPassWithShader( j, shader, 0 ); + vbo.DrawChunk (*channels); + GPU_TIMESTAMP(); + } + } + } + else + { + // cube mapped skybox + for (int pass = 0; pass < passCount; pass++) + { + mat->SetPassWithShader( pass, shader, 0 ); + device.ImmediateBegin( kPrimitiveQuads ); + const SkyboxVertex* verts = kSkyboxVB; + for ( int i = 0; i < kSkyboxVertexCount; i++ ) { + device.ImmediateTexCoordAll( verts->x, verts->y, verts->z ); + device.ImmediateVertex( verts->x, verts->y, verts->z ); + ++verts; + } + device.ImmediateEnd(); + GPU_TIMESTAMP(); + } + } +} + +void Skybox::SetMaterial (Material* material) { + m_CustomSkybox = material; +} + +Material* Skybox::GetMaterial ()const { + return m_CustomSkybox; +} + +template +void Skybox::Transfer (TransferFunction& transfer) { + Super::Transfer (transfer); + TRANSFER_SIMPLE (m_CustomSkybox); +} + +IMPLEMENT_CLASS (Skybox) +IMPLEMENT_OBJECT_SERIALIZE (Skybox) -- cgit v1.1-26-g67d0