如何将自定义结构从顶点着色器传递到片段着色器 [英] How to pass a custom struct from vertex shader to fragment shader

查看:63
本文介绍了如何将自定义结构从顶点着色器传递到片段着色器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在片段着色器中,我定义了以下两个结构

  struct DirLight {vec3方向;vec3环境;vec3扩散;vec3镜面反射;};struct PointLight {vec3位置;vec3环境;vec3扩散;vec3镜面反射;浮点常数线性浮动二次方浮点数}; 

在顶点着色器中,我定义了以下变量,因为我首先要对顶点着色器中的这些统一变量进行一些转换(例如片段着色器中不建议使用的矩阵乘法).

 统一的DirLight dirLight;//只有一个定向灯均匀int pointLightCnt;//点光源的数量统一PointLight pointLight [MAX];//点光源 

我该怎么做才能将顶点着色器中的结构转移到片段着色器中?

我可以使用一种类似于c ++的方法:在头文件中定义结构,在顶点着色器片段着色器包括它们,然后定义在顶点着色器中相应的 out 变量,并在 fragment shader 中定义相应的 in 变量来实现它?

解决方案

我将详细解释如何实现您的照明结构,因此它对任何照明类型都是通用的,但这是一个单独的问题./p>

您当前的问题是顶点功能"根本不需要使用照明制服.它们之间没有数据可传递.顶点着色器唯一要做的就是将局部空间转换为剪贴空间,并将中间世界空间保存为片段着色器输入的单独部分,以便可以正确计算照明.

所有照明计算都可以在像素/片段着色器上进行,并且任何动态照明(位置,半影计算,方向更改等)都应在CPU上完成,并仅通过照明缓冲区/统一传递给GPU.全部一次.

这在hlsl中,但是很容易转换为glsl:

 //统一cbuffer matrix_cb:寄存器(b0){float4x4 g_MODEL;float4x4 g_VIEW;float4x4 g_PROJECTION;};struct vs_in_t {float3位置:POSITION;float4颜色:COLOR;float2 uv:紫外线;float4 normal:NORMAL;};struct ps_in_t {float4位置:SV_POSITION;float4颜色:COLOR;float2 uv:紫外线;float4 normal:NORMAL;float3 world_position:WORLD;};ps_in_t VertexFunction(vs_in_t input_vertex){ps_in_t输出;float4 local = float4(input_vertex.position,1.0f);float4 normal = input_vertex.normal;float4 world = mul(local,g_MODEL);float4 view = mul(world,g_VIEW);float4 clip = mul(view,g_PROJECTION);output.position =剪辑;output.color = input_vertex.color;output.uv = input_vertex.uv;output.normal =正常;output.world_position = world.xyz;返回输出;} 

In the fragment shader, I defined two structures as follows

struct DirLight{
    vec3 direction;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

struct PointLight {
    vec3 position;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float constant;
    float linear; 
    float quadratic;
};

and in vertex shader, I defined the following variables, because I first want to do some transformations (like matrix multiplication that is not recommended in the fragment shader) on these uniform variables in the vertex shader.

uniform DirLight dirLight; // only one directional light
uniform int pointLightCnt; // number of point light sources
uniform PointLight pointLight[MAX]; // point lights

What should I do to transfer the structure in the vertex shader to the fragment shader?

Can I use a method similar to c++ like: Define the structure in the header file, include them in both the vertex shader and the fragment shader, then define the corresponding out variable in the vertex shader, and define the corresponding in variable in the fragment shader to achieve it?

解决方案

I was going to go into a long explanation of how to implement your lighting structure so it is generic to any light type, but that is a separate issue.

Your current issue is that the Vertex Function shouldn't need to use the lighting uniform at all; there's no data to pass between them. The only thing the Vertex shader should be doing is converting the local space to clip space and saving the intermediate world space as a separate part of the fragment shader's input so it can calculate the lighting properly.

All the lighting calculations can be done on the pixel/fragment shader and any dynamic lighting (positions, penumbra calculations, direction changes, etc) should be done on the CPU and just passed on to the GPU in the lighting buffer/uniform all at once.

This is in hlsl, but it's easily converted to glsl:

//Uniform
cbuffer matrix_cb : register(b0) {
    float4x4 g_MODEL;
    float4x4 g_VIEW;
    float4x4 g_PROJECTION;
};

struct vs_in_t {
    float3 position : POSITION;
    float4 color : COLOR;
    float2 uv : UV;
    float4 normal : NORMAL;
};

struct ps_in_t {
    float4 position : SV_POSITION;
    float4 color : COLOR;
    float2 uv : UV;
    float4 normal : NORMAL;
    float3 world_position : WORLD;
};

ps_in_t VertexFunction(vs_in_t input_vertex) {
    ps_in_t output;

    float4 local = float4(input_vertex.position, 1.0f);
    float4 normal = input_vertex.normal;
    float4 world = mul(local, g_MODEL);
    float4 view = mul(world, g_VIEW);
    float4 clip = mul(view, g_PROJECTION);

    output.position = clip;
    output.color = input_vertex.color;
    output.uv = input_vertex.uv;
    output.normal = normal;
    output.world_position = world.xyz;

    return output;
}

这篇关于如何将自定义结构从顶点着色器传递到片段着色器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆