// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include #include #include #include namespace Nz { namespace { /*! * \brief Builds the shader for the fog * \return Reference to the shader newly created */ ShaderRef BuildFogShader() { /*const UInt8 fragmentSource[] = { #include };*/ const char* fragmentSource = "#version 140\n" "out vec4 RenderTarget0;\n" "uniform sampler2D ColorTexture;\n" "uniform sampler2D GBuffer2;\n" "uniform mat4 InvViewProjMatrix;\n" "uniform vec2 InvTargetSize;\n" "uniform vec3 EyePosition;\n" "float n = 0.1;" "float f = 1000.0;" "float color_to_float(vec3 color)\n" "{\n" "const vec3 byte_to_float = vec3(1.0, 1.0/256, 1.0/(256*256));\n" "return dot(color, byte_to_float);\n" "}\n" "void main()\n" "{" "vec2 texCoord = gl_FragCoord.xy * InvTargetSize;\n" "\t" "vec3 color = texture(ColorTexture, texCoord).xyz;\n" "vec4 gVec2 = textureLod(GBuffer2, texCoord, 0.0);\n" "float depth = color_to_float(gVec2.xyz)*2.0 - 1.0;\n" "float linearDepth = (2 * n) / (f + n - depth * (f - n));" "vec3 viewSpace = vec3(texCoord*2.0 - 1.0, depth);\n" "vec4 worldPos = InvViewProjMatrix * vec4(viewSpace, 1.0);\n" "worldPos.xyz /= worldPos.w;\n" /*"float lumThreshold = 0.1;" "float lumMultipler = 2.0;" //"float lumFactor = max(dot(color, vec3(0.299, 0.587, 0.114)) - lumThreshold, 0.0) / (1.0-lumThreshold);" "float fogFactor = (1.0 - clamp(worldPos.y-2.0, 0.0, 1.0)) - lumFactor*lumMultipler;" "fogFactor += (1.0 - clamp(EyePosition.y-2.5, 0.0, 1.0));" "fogFactor = clamp(fogFactor, 0.0, 1.0);"*/ "float lumThreshold = 0.8;" "float lumMultipler = 2.0;" "float luminosity = dot(color, vec3(0.299, 0.587, 0.114));" "float lumFactor = max(luminosity - lumThreshold, 0.0) / (1.0-lumThreshold);" "vec4 fogColor = vec4(0.5, 0.5, 0.5, 1.0);\n" "vec2 fogrange = vec2(0, 50);\n" "float fogeffect = clamp( 1.0 - (fogrange.y - linearDepth*0.5*f) / (fogrange.y - fogrange.x) , 0.0, 1.0 ) * fogColor.w;\n" "fogeffect = max(fogeffect-lumFactor, 0.0);" //fogeffect*=(1.0 - int(depth)); "\t" "vec3 fragmentColor = color*(1.0-fogeffect) + fogColor.rgb * fogeffect;\n" "\t" "RenderTarget0 = vec4(fragmentColor, 1.0);\n" "}"; const char* vertexSource = "#version 140\n" "in vec3 VertexPosition;\n" "void main()\n" "{\n" "\t" "gl_Position = vec4(VertexPosition, 1.0);" "\n" "}\n"; ///TODO: Remplacer ça par des ShaderNode ShaderRef shader = Shader::New(); if (!shader->Create()) { NazaraError("Failed to load create shader"); return nullptr; } if (!shader->AttachStageFromSource(ShaderStageType_Fragment, fragmentSource/*String(reinterpret_cast(fragmentSource), sizeof(fragmentSource))*/)) { NazaraError("Failed to load fragment shader"); return nullptr; } if (!shader->AttachStageFromSource(ShaderStageType_Vertex, vertexSource)) { NazaraError("Failed to load vertex shader"); return nullptr; } if (!shader->Link()) { NazaraError("Failed to link shader"); return nullptr; } shader->SendInteger(shader->GetUniformLocation("ColorTexture"), 0); shader->SendInteger(shader->GetUniformLocation("GBuffer2"), 1); return shader; } } /*! * \ingroup graphics * \class Nz::DeferredFogPass * \brief Graphics class that represents the pass for fog in deferred rendering */ /*! * \brief Constructs a DeferredFogPass object by default */ DeferredFogPass::DeferredFogPass() { m_pointSampler.SetAnisotropyLevel(1); m_pointSampler.SetFilterMode(SamplerFilter_Nearest); m_pointSampler.SetWrapMode(SamplerWrap_Clamp); m_shader = BuildFogShader(); m_shaderEyePositionLocation = m_shader->GetUniformLocation("EyePosition"); m_states.depthBuffer = false; } DeferredFogPass::~DeferredFogPass() = default; /*! * \brief Processes the work on the data while working with textures * \return true * * \param sceneData Data for the scene * \param firstWorkTexture Index of the first texture to work with * \param firstWorkTexture Index of the second texture to work with */ bool DeferredFogPass::Process( const SceneData& sceneData, unsigned int firstWorkTexture, unsigned int secondWorkTexture) const { NazaraAssert(sceneData.viewer, "Invalid viewer"); m_workRTT->SetColorTarget(firstWorkTexture); Renderer::SetTarget(m_workRTT); Renderer::SetViewport(Recti(0, 0, m_dimensions.x, m_dimensions.y)); Renderer::SetShader(m_shader); m_shader->SendVector(m_shaderEyePositionLocation, sceneData.viewer->GetEyePosition()); Renderer::SetRenderStates(m_states); Renderer::SetTexture(0, m_workTextures[secondWorkTexture]); Renderer::SetTexture(1, m_GBuffer[2]); Renderer::SetTextureSampler(0, m_pointSampler); Renderer::SetTextureSampler(1, m_pointSampler); Renderer::DrawFullscreenQuad(); return true; } }