Browse Source

Added "refract" pass to default renderpaths. This has the rendered scene so far (opaque + sky) available in the environment texture unit.
Renamed the "prealpha" pass to "postopaque" (will break custom techniques and renderpaths referring to prealpha.)
If a scene pass has nothing to render, skip it completely during View processing, including rendertarget allocations. This makes the refract pass free when there is no refractive geometry.

Lasse Öörni 12 years ago
parent
commit
f9a6235f47

+ 4 - 1
Bin/CoreData/RenderPaths/Deferred.xml

@@ -14,7 +14,10 @@
         <texture unit="normal" name="normal" />
         <texture unit="depth" name="depth" />
     </command>
-    <command type="scenepass" pass="prealpha" />
+    <command type="scenepass" pass="postopaque" />
+    <command type="scenepass" pass="refract">
+        <texture unit="environment" name="viewport" />
+    </command>
     <command type="scenepass" pass="alpha" usescissor="true" vertexlights="true" sort="backtofront" metadata="alpha" />
     <command type="scenepass" pass="postalpha" sort="backtofront" />
 </renderpath>

+ 4 - 1
Bin/CoreData/RenderPaths/Forward.xml

@@ -2,7 +2,10 @@
     <command type="clear" color="fog" depth="1.0" stencil="0" />
     <command type="scenepass" pass="base" vertexlights="true" metadata="base" />
     <command type="forwardlights" pass="light" />
-    <command type="scenepass" pass="prealpha" />
+    <command type="scenepass" pass="postopaque" />
+    <command type="scenepass" pass="refract">
+        <texture unit="environment" name="viewport" />
+    </command>
     <command type="scenepass" pass="alpha" usescissor="true" vertexlights="true" sort="backtofront" metadata="alpha" />
     <command type="scenepass" pass="postalpha" sort="backtofront" />
 </renderpath>

+ 4 - 1
Bin/CoreData/RenderPaths/ForwardDepth.xml

@@ -5,7 +5,10 @@
     <command type="clear" color="fog" depth="1.0" stencil="0" />
     <command type="scenepass" pass="base" vertexlights="true" metadata="base" />
     <command type="forwardlights" pass="light" />
-    <command type="scenepass" pass="prealpha" />
+    <command type="scenepass" pass="postopaque" />
+    <command type="scenepass" pass="refract">
+        <texture unit="environment" name="viewport" />
+    </command>
     <command type="scenepass" pass="alpha" usescissor="true" vertexlights="true" sort="backtofront" metadata="alpha" />
     <command type="scenepass" pass="postalpha" sort="backtofront" />
 </renderpath>

+ 4 - 1
Bin/CoreData/RenderPaths/Prepass.xml

@@ -15,7 +15,10 @@
     <command type="scenepass" pass="material" vertexlights="true">
         <texture unit="light" name="light" />
     </command>
-    <command type="scenepass" pass="prealpha"/>
+    <command type="scenepass" pass="postopaque" />
+    <command type="scenepass" pass="refract">
+        <texture unit="environment" name="viewport" />
+    </command>
     <command type="scenepass" pass="alpha" usescissor="true" vertexlights="true" sort="backtofront" metadata="alpha" />
     <command type="scenepass" pass="postalpha" sort="backtofront" />
 </renderpath>

+ 1 - 1
Bin/CoreData/Techniques/DiffSkybox.xml

@@ -1,3 +1,3 @@
 <technique>
-    <pass name="prealpha" vs="Skybox" ps="Skybox" depthwrite="false" />
+    <pass name="postopaque" vs="Skybox" ps="Skybox" depthwrite="false" />
 </technique>

+ 5 - 2
Docs/Reference.dox

@@ -894,7 +894,7 @@ A technique definition looks like this:
 
 \code
 <technique>
-    <pass name="base|litbase|light|alpha|litalpha|prealpha|postalpha|prepass|material|deferred|depth|shadow" vs="VertexShaderName" ps="PixelShaderName"
+    <pass name="base|litbase|light|alpha|litalpha|postopaque|refract|postalpha|prepass|material|deferred|depth|shadow" vs="VertexShaderName" ps="PixelShaderName"
         lighting="unlit|pervertex|perpixel" alphatest="true|false" blend="replace|add|multiply|alpha|addalpha|premulalpha|invdestalpha"
         depthtest="always|equal|less|lessequal|greater|greaterequal" depthwrite="true|false" alphamask="true|false" />
     <pass ... />
@@ -909,7 +909,8 @@ The purposes of the different passes are:
 - light: Renders one per-pixel light's contribution additively for an opaque object.
 - alpha: Renders ambient light, per-vertex lights and fog for a transparent object.
 - litalpha: Renders one per-pixel light's contribution additively for a transparent object
-- prealpha: Custom rendering pass after opaque geometry. Can be used for example to render the skybox.
+- postopaque: Custom rendering pass after opaque geometry. Can be used to render the skybox.
+- refract: Custom rendering pass after postopaque pass. Can sample the viewport texture from the environment texture unit to render refractive objects.
 - postalpha: Custom rendering pass after transparent geometry.
 - prepass: %Light pre-pass only - renders normals, specular power and depth to the G-buffer.
 - material: %Light pre-pass only - renders opaque geometry final color by combining ambient light, per-vertex lights and per-pixel light accumulation.
@@ -927,6 +928,8 @@ The optional "litbase" pass reduces draw call count by combining ambient lightin
 
 "Alphamask" is not an actual rendering state, but a hint which tells that the pixel shader will use discard based on alpha. Because this may interfere with the early-Z culling, materials without the alpha masking hint will be drawn first.
 
+The refract pass requires pingponging the scene rendertarget to a texture, but this will not be performed if there is no refractive geometry to render, so there is no unnecessary cost to it.
+
 
 \page Shaders Shaders
 

+ 2 - 1
Source/Engine/Graphics/GraphicsDefs.cpp

@@ -76,7 +76,8 @@ StringHash PASS_SHADOW("shadow");
 StringHash PASS_DEFERRED("deferred");
 StringHash PASS_PREPASS("prepass");
 StringHash PASS_MATERIAL("material");
-StringHash PASS_PREALPHA("prealpha");
+StringHash PASS_POSTOPAQUE("postopaque");
+StringHash PASS_REFRACT("refract");
 StringHash PASS_POSTALPHA("postalpha");
 
 Vector3 DOT_SCALE(1 / 3.0f, 1 / 3.0f, 1 / 3.0f);

+ 2 - 1
Source/Engine/Graphics/GraphicsDefs.h

@@ -244,7 +244,8 @@ extern StringHash PASS_SHADOW;
 extern StringHash PASS_DEFERRED;
 extern StringHash PASS_PREPASS;
 extern StringHash PASS_MATERIAL;
-extern StringHash PASS_PREALPHA;
+extern StringHash PASS_POSTOPAQUE;
+extern StringHash PASS_REFRACT;
 extern StringHash PASS_POSTALPHA;
 
 // Scale calculation from bounding box diagonal.

+ 11 - 4
Source/Engine/Graphics/View.cpp

@@ -1078,11 +1078,13 @@ void View::UpdateGeometries()
         for (unsigned i = 0; i < renderPath_->commands_.Size(); ++i)
         {
             const RenderPathCommand& command = renderPath_->commands_[i];
-            if (!command.enabled_)
+            if (!IsNecessary(command))
                 continue;
             
             if (command.type_ == CMD_SCENEPASS)
             {
+                BatchQueue* passQueue = &batchQueues_[command.pass_];
+                
                 item.workFunction_ = command.sortMode_ == SORT_FRONTTOBACK ? SortBatchQueueFrontToBackWork :
                     SortBatchQueueBackToFrontWork;
                 item.start_ = &batchQueues_[command.pass_];
@@ -1248,7 +1250,7 @@ void View::ExecuteRenderPathCommands()
         unsigned lastCommandIndex = 0;
         for (unsigned i = 0; i < renderPath_->commands_.Size(); ++i)
         {
-            if (!renderPath_->commands_[i].enabled_)
+            if (!IsNecessary(renderPath_->commands_[i]))
                 continue;
             lastCommandIndex = i;
         }
@@ -1256,7 +1258,7 @@ void View::ExecuteRenderPathCommands()
         for (unsigned i = 0; i < renderPath_->commands_.Size(); ++i)
         {
             RenderPathCommand& command = renderPath_->commands_[i];
-            if (!command.enabled_)
+            if (!IsNecessary(command))
                 continue;
             
             // If command writes and reads the target at same time, pingpong automatically
@@ -1573,6 +1575,11 @@ void View::RenderQuad(RenderPathCommand& command)
     DrawFullscreenQuad(false);
 }
 
+bool View::IsNecessary(const RenderPathCommand& command)
+{
+    return command.enabled_ && (command.type_ != CMD_SCENEPASS || !batchQueues_[command.pass_].IsEmpty());
+}
+
 bool View::CheckViewportRead(const RenderPathCommand& command)
 {
     for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
@@ -1614,7 +1621,7 @@ void View::AllocateScreenBuffers()
     for (unsigned i = 0; i < renderPath_->commands_.Size(); ++i)
     {
         const RenderPathCommand& command = renderPath_->commands_[i];
-        if (!command.enabled_)
+        if (!IsNecessary(command))
             continue;
         if (CheckViewportRead(command))
         {

+ 2 - 0
Source/Engine/Graphics/View.h

@@ -161,6 +161,8 @@ private:
     void SetTextures(RenderPathCommand& command);
     /// Perform a quad rendering command.
     void RenderQuad(RenderPathCommand& command);
+    /// Check if a command is enabled and has content to render. To be called only after render update has completed for the frame.
+    bool IsNecessary(const RenderPathCommand& command);
     /// Check if a command reads the rendered scene.
     bool CheckViewportRead(const RenderPathCommand& command);
     /// Allocate needed screen buffers.