gpt4 book ai didi

opengl - 什么是 channel 和多个着色器 channel 及其私有(private)变量

转载 作者:行者123 更新时间:2023-12-01 14:38:44 25 4
gpt4 key购买 nike

我知道多 channel 渲染是关于渲染场景的单独部分并将它们组合成图像并应用混合因子,这已在渲染图形中完成。但是什么是通行证和
什么是着色器中的多次传递。例如下面的着色器用于第一个光的漫射照明:

Shader "Cg per-vertex diffuse lighting" {
Properties {
_Color ("Diffuse Material Color", Color) = (1,1,1,1)
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
// make sure that all uniforms are correctly set

CGPROGRAM

#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"

uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc")

uniform float4 _Color; // define shader property for shaders

struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 col : COLOR;
};

vertexOutput vert(vertexInput input)
{
vertexOutput output;

float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object;
// multiplication with unity_Scale.w is unnecessary
// because we normalize transformed vectors

float3 normalDirection = normalize(float3(
mul(float4(input.normal, 0.0), modelMatrixInverse)));
float3 lightDirection = normalize(
float3(_WorldSpaceLightPos0));

float3 diffuseReflection =
float3(_LightColor0) * float3(_Color)
* max(0.0, dot(normalDirection, lightDirection));

output.col = float4(diffuseReflection, 1.0);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
}

float4 frag(vertexOutput input) : COLOR
{
return input.col;
}

ENDCG
}
}
// The definition of a fallback shader should be commented out
// during development:
// Fallback "Diffuse"
}

下面的着色器再次用于具有多个 channel 和多个灯光的漫反射照明。

在下面的着色器中,两个 channel 中的代码是相同的,在第二个 channel 中,着色器指向 _LightColor0 同样在第一遍中,着色器正在使用 _LightColor0 .那么多灯在哪里呢?两个 channel 都指向 _LightColor0 .我想,两次传球都在使用第一道光。

通行证有它的私有(private)灯光阵列是真的吗?
Shader "Cg per-vertex diffuse lighting" {
Properties {
_Color ("Diffuse Material Color", Color) = (1,1,1,1)
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
// pass for first light source

CGPROGRAM

#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"

uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc")

uniform float4 _Color; // define shader property for shaders

struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 col : COLOR;
};

vertexOutput vert(vertexInput input)
{
vertexOutput output;

float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object;
// multiplication with unity_Scale.w is unnecessary
// because we normalize transformed vectors

float3 normalDirection = normalize(float3(
mul(float4(input.normal, 0.0), modelMatrixInverse)));
float3 lightDirection = normalize(
float3(_WorldSpaceLightPos0));

float3 diffuseReflection =
float3(_LightColor0) * float3(_Color)
* max(0.0, dot(normalDirection, lightDirection));

output.col = float4(diffuseReflection, 1.0);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
}

float4 frag(vertexOutput input) : COLOR
{
return input.col;
}

ENDCG
}

Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend One One // additive blending

CGPROGRAM

#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"

uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc")

uniform float4 _Color; // define shader property for shaders

struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 col : COLOR;
};

vertexOutput vert(vertexInput input)
{
vertexOutput output;

float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object;
// multiplication with unity_Scale.w is unnecessary
// because we normalize transformed vectors

float3 normalDirection = normalize(float3(
mul(float4(input.normal, 0.0), modelMatrixInverse)));
float3 lightDirection = normalize(
float3(_WorldSpaceLightPos0));

float3 diffuseReflection =
float3(_LightColor0) * float3(_Color)
* max(0.0, dot(normalDirection, lightDirection));

output.col = float4(diffuseReflection, 1.0);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
}

float4 frag(vertexOutput input) : COLOR
{
return input.col;
}

ENDCG
}
}
// The definition of a fallback shader should be commented out
// during development:
// Fallback "Diffuse"
}

更新:这个着色器适用于多个灯光,因为我已经在下面的立方体上测试了三个
三种不同颜色的灯,结果如下:

enter image description here
提前致谢

最佳答案

一般来说,像这样的高级着色器/ Material 系统(是的,高于 GLSL/Cg/HLSL)中的 channel 是设置多 channel 渲染所需状态的一种方式。如果您直接与 GLSL、Cg 或 HLSL 打交道,则没有“通过”之类的东西。

在这种情况下,您有两个不同的 类型 channel 数,因为一个建立了基础照明贡献,并且每个连续的 channel 都会增加它。换句话说,它们具有不同的混合功能。第一次通过替换帧缓冲区中的任何内容(如果您熟悉 OpenGL,则有效地为 glBlendFunc (GL_ONE, GL_ZERO)),第二次通过将计算的光添加到所有先前的通过(glBlendFunc (GL_ONE, GL_ONE))。

不要想 _LightColor0 好像它指的是场景中的第一盏灯。实际上,它是光照 channel 处理的一组灯光中的第一个灯光(在本例中,每个灯光 1 个 channel )。如果此着色器能够在每个 channel 中处理多个灯光,您可能会看到 _LightColor0 - _LightColorN 并且所需的通过次数大致如下:1 + ceil ((NumLights-1)/(_LightColorN+1))。

这个丑陋的着色器需要对每个顶点进行光照,并且需要对每个光照进行 1 次传递。即使对于前向渲染,这也是非常低效的。如果使用阴影贴图,我可以理解需要多个 channel ,但这与您可以获得的照明着色器一样简单,并且它仍然需要每个光照 1 个 channel 。即使是古老的固定功能硬件,每次也可以做 8 个灯。

更新:

由于对于每个灯光如何与此着色器中的 channel 相关存在一些混淆,并且您已更新您的问题以包含图表,因此我将使用图表来解释这一点。

Lights

在此图中,有三个光源。要使用此着色器应用这三个灯光需要三个 channel 。

Pass 0: <Yellow Light>
Blend Function: Framebuffer = (1 * Light) + (0 * Framebuffer)
Pass Type: "ForwardBase"

Pass 1: <Red Light>
Blend Function: Framebuffer = (1 * Light) + (1 * Framebuffer)
Pass Type: "ForwardAdd"

Pass 2: <Green Light>
Blend Function: Framebuffer = (1 * Light) + (1 * Framebuffer)
Pass Type: "ForwardAdd"

最终的结果是这样的:
Final Color = Light0 + Light1 + Light2

如果你有更多的灯,他们都会使用 ForwardAdd从你的着色器传递。顺便说一句,由于颜色值被限制为 0.0 - 1.0 混合后,每盏灯都将其强度添加到所有先前的灯中,在灯光变为纯白色之前不需要太多灯。除非您使用 HDR(高动态范围)来解决此问题,否则在使用附加照明时必须非常小心。

关于多次绘制立方体的过程,GPU与此无关。图形引擎本身会改变每个着色器 channel 的状态并重新绘制立方体。由于像混合函数这样的状态变化不能在每个实例中更改,引擎实际上已经绘制了一次立方体,更改了一些状态,然后使用此着色器再次绘制它。这个过程称为批处理,当您开始绘制不仅仅是一个简单的立方体时,它会变得更加复杂。

减少必须绘制立方体的次数对于实现高性能非常重要。当使用许多灯时,引擎通常从 切换。转发 底纹到 延期 .这会将立方体一次绘制到多个纹理中,每个纹理存储一个或多个计算光照所需的属性,例如位置、光泽度、反照率、法线、 Material ID 等。当需要应用光照时,而不是绘制立方体一遍又一遍地,从片段/计算着色器中的预计算纹理(G-Buffers)中查找属性。

问题是,延迟着色不用于逐顶点照明,并且所涉及的整体增加的复杂性/内存要求可能使其在仅使用 2 或 3 盏灯时变得不切实际。

关于opengl - 什么是 channel 和多个着色器 channel 及其私有(private)变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21079675/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com