Quad rendering via PassQuad in GL3Plus RS Topic is solved

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


User avatar
bishopnator
Gnome
Posts: 379
Joined: Thu Apr 26, 2007 11:43 am
Location: Slovakia / Switzerland
x 18

Quad rendering via PassQuad in GL3Plus RS

Post by bishopnator »

Hi, I am getting strange problem with the full-screen quad rendering with GL3Plus RS. The RenderDoc is showing me that input vertex buffer has all vertices (0, 0, 0). I check the full-screen triangle and full-screen quad as well. Both meshes have same problem according to the RenderDoc.
Image

However, if I check the content of the buffer, the values seems to be correct there:
Image

Here is my vertex shader for the quad in HLSL:

Code: Select all

// vertex shader input attributes
struct vs_in
{
	float4 position : POSITION;
};

// vertex shader output attributes
struct vs_out
{
	float4 position : SV_POSITION; // required output of VS
	float2 uv : TEXCOORD0;
};

vs_out main(vs_in input)
{
	vs_out output = (vs_out)0; // zero the memory first
	output.position = float4(input.position.xy, 0.0, 1.0);
	
// convert range <-1, 1> to <0, 1>
output.uv = (input.position.xy + float2(1, 1)) * 0.5 * float2(1, -1); // flip y-axis

return output;
}

Here is the vertex shader for the quad in GLSL (automatically converted from HLSL through spir-v:

Code: Select all

#version 450
layout(std140) uniform;


layout(location = 0) in vec4 input_position;
layout(location = 0) out vec2 _entryPointOutput_uv;

void main()
{
    gl_Position = vec4(input_position.xy, 0.0, 1.0);
    _entryPointOutput_uv = ((input_position.xy + vec2(1.0)) * 0.5) * vec2(1.0, -1.0);
}

Note1: in D3D11 render system there is no problem and the rendering looks as expected:
Image

Note2: I am using my custom HLMS implementation where I implemented fillBuffersFor as it is called for the v1::Rectangle2D - I mostly copied the implementation from the HlmsLowLevel::fillBuffersFor (and HlmsLowLevel::executeCommand), but there is nothing related to binding of the vertex/index buffers of the renderable and as my code is working for D3D11, I suppose it should be somehow correct).

The OpenGL doesn't report me any errors, there is no special errors logged aldo from ogre in log file. What could cause such problems in OpenGL?

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5571
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1405

Re: Quad rendering via PassQuad in GL3Plus RS

Post by dark_sylinc »

Hi,

Due to long historic reasons, the name of the input attributes (for GL3+) in vertex shader matters. Your input_position variable should be renamed to vertex and then it will start working.

The same happens with any UVs (uv0 - uv7).

User avatar
bishopnator
Gnome
Posts: 379
Joined: Thu Apr 26, 2007 11:43 am
Location: Slovakia / Switzerland
x 18

Re: Quad rendering via PassQuad in GL3Plus RS

Post by bishopnator »

Thx, that helped to get the vertices in shader with correct values. Now I see in GL3Plus that the quad (or triangle) is actually clipped and I need to add multiplication of vec2(1, -1) to the coordinates to flip the geometry. How is it solved within the Ogre? I am sure there is a trick. Is it necessary to upload a projection matrix there? Normally for the full-screen quad I tend to avoid any matrix multiplications as the output geometry is pretty clear how it should look like. Or is it better to just turn-off the winding order? What is the preferred way?

User avatar
bishopnator
Gnome
Posts: 379
Joined: Thu Apr 26, 2007 11:43 am
Location: Slovakia / Switzerland
x 18

Re: Quad rendering via PassQuad in GL3Plus RS

Post by bishopnator »

I checked how the quads are rendered in Ogre and I see that the vertex shaders use the view-projection matrix to transform the vertices. It was little bit tricky to get it working with my HLMS implementation, because the HlmsLowLevel uses AutoParamDataSource and the view-projection matrix is uploaded within HlmsLowLevel::fillBuffersFor where the AutoParamDataSource has access to the current renderable (and hence it is possible to call mCurrentRenderable->getUseIdentityProjection()).

In my implementation, the view-projection matrix is filled to the pass buffer in onPreparePassHash where there is no access to the renderable. I created custom camera with "identity" view and projection matrix and use that in PassQuad as camera name. Another complication is, that fillBuffersFor doesn't have access to CommandBuffer. I tricked it by creating a temporary command buffer on stack and executing it immediately:

Code: Select all

	// Ensure that the pass buffer is bound.
	CommandBuffer commandBuffer;
	commandBuffer.setCurrentRenderSystem(mRenderSystem);
	mPassBufferPool->bindBuffer(&commandBuffer);
	commandBuffer.execute();

Then I can access the pass data in my quad vertex shader as in other HLMS shaders and properly transform the full-screen quad (or triangle). It looks like it is working as expected. Just for reference, here are updated shaders:

HLSL

Code: Select all

// pass buffer
#include "PassData.h"
cbuffer PassBuffer : register(b0)
{
	PassData passData;
};
	
// vertex shader input attributes
struct vs_in
{
	float4 position : POSITION;
	float2 uv : TEXCOORD0;
};

// vertex shader output attributes
struct vs_out
{
	float4 position : SV_POSITION; // required output of VS
	float2 uv : TEXCOORD0;
};

vs_out main(vs_in input)
{
	vs_out output = (vs_out)0; // zero the memory first
	output.position = mul(input.position, passData.viewProjectionMatrix);
	output.uv = input.uv;
	return output;
}

GLSL (converted HLSL through spir-v)

Code: Select all

#version 450
layout(std140) uniform;

struct PassData
{
    mat4 viewMatrix;
    mat4 viewProjectionMatrix;
    mat4 projectionMatrix;
    vec4 depthRange;
    vec4 renderTargetInfo;
    vec4 ppu;
    vec4 priorityCount;
};

layout(binding = 0, std140) uniform PassBuffer
{
    layout(row_major) PassData passData;
} _28;

layout(location = 0) in vec4 vertex;
layout(location = 7) in vec2 uv0;
layout(location = 0) out vec2 _entryPointOutput_uv;

mat4 spvWorkaroundRowMajor(mat4 wrap) { return wrap; }

void main()
{
    gl_Position = spvWorkaroundRowMajor(_28.passData.viewProjectionMatrix) * vertex;
    _entryPointOutput_uv = uv0;
}
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5571
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1405

Re: Quad rendering via PassQuad in GL3Plus RS

Post by dark_sylinc »

Hi! Sorry for the late reply.

It is indeed correct. Even an identity projection matrix isn't truly identity because we use it to do tricks to counter API differences.

In the OpenGL case, the projection matrix will flip your vertices based on whether RenderPassDescriptor::requiresTextureFlipping returns true.

If you want to avoid the projection matrix multiplication, you can manually account for RenderPassDescriptor::requiresTextureFlipping (note that the return value can change depending on whether the target is a RenderTexture or a Window).