gpt4 book ai didi

opengl - glsl片段着色器如何从每个顶点获取非插值数据

转载 作者:行者123 更新时间:2023-12-02 01:14:13 26 4
gpt4 key购买 nike

tl;博士:在片段着色器中访问每个单独顶点的数据的最佳方法是什么?

例如该片段中的三角形由顶点 v0、v1 和 v2 组成,我想给每个顶点一个特定的整数,我可以用它来选择纹理,然后在片段着色器中的 3 个纹理之间淡入淡出;我不希望对这些 id 进行插值,并且能够访问每个顶点的 id 很重要。

当前情况:我目前正在编写一个用于渲染地形的着色器;我的片段着色器中有一个函数,它将从给定 ID 的 uvs 返回适当的纹理颜色(通过纹理图集)。然后我可以在 3 个纹理之间淡入淡出,以提供平滑的纹理地形

当前代码

顶点着色器:

#version 330 core

layout(location = 0) in vec3 in_position;
layout(location = 1) in vec2 in_uv_coords;
layout(location = 2) in vec3 in_normal;
layout(location = 3) in float in_texture_id;

uniform mat4 view_matrix;
uniform mat4 projection_matrix;

out vec2 pass_uv_coords;
out vec3 pass_normal;

out vec3 texture_ratio;
out float pass_fake_brightness;

out float pass_id0;
out float pass_id1;
out float pass_id2;


void CalculateFakeLighting()
{
const vec3 light_direction = normalize(vec3(1,-1,1));
vec3 unit_normal = normalize(in_normal);

float normal_dot_light = dot(unit_normal, -light_direction);
pass_fake_brightness = max(0.2, normal_dot_light);
}


void main()
{
pass_uv_coords = in_uv_coords;
pass_normal = in_normal;

gl_Position = projection_matrix * view_matrix * vec4(in_position, 1.0);

int tile_track = int(mod(gl_VertexID, 3));

switch(tile_track)
{
case 0:
texture_ratio = vec3(1,0,0);
pass_id0 = in_texture_id;
break;
case 1:
texture_ratio = vec3(0,1,0);
pass_id1 = in_texture_id;
break;
case 2:
texture_ratio = vec3(0,0,1);
pass_id0 = in_texture_id;
break;
};

CalculateFakeLighting();
}

片段着色器:

#version 330 core

in vec2 pass_uv_coords;
in vec3 pass_normal;

in vec3 texture_ratio;
in float pass_fake_brightness;

in float pass_id0;
in float pass_id1;
in float pass_id2;

const int HORIZONTAL_IDS = 8;
const int VERTICAL_IDS = 8;

uniform sampler2D texture0_sampler;

out vec4 colour;


void UseFakeLighting()
{
colour *= pass_fake_brightness;
}

vec2 CorrectUVs(vec2 uvs)
{
vec2 corrected_uvs = uvs;
const float cushion = 0.001;

//Correct UV scale
while(corrected_uvs.x >= 1)
corrected_uvs.x--;
while(corrected_uvs.y >= 1)
corrected_uvs.y--;

if(corrected_uvs.x < cushion)
corrected_uvs.x = cushion;
if(corrected_uvs.x > 1 - cushion)
corrected_uvs.x = 1 - cushion;

if(corrected_uvs.y < cushion)
corrected_uvs.y = cushion;
if(corrected_uvs.y > 1 - cushion)
corrected_uvs.y = 1 - cushion;

return corrected_uvs;
}


vec4 GetTexture(float id, vec2 uv_coords)
{
vec2 step = vec2(
1.0/HORIZONTAL_IDS,
1.0/VERTICAL_IDS
);


uv_coords.x/=HORIZONTAL_IDS;
uv_coords.y/=VERTICAL_IDS;

uv_coords.x += step.x * mod(id, HORIZONTAL_IDS);
uv_coords.y += step.y * floor(id/VERTICAL_IDS);
//Texture is upsidedown
uv_coords.y = 1.0 - uv_coords.y;

return texture(texture0_sampler, uv_coords);
}


void main()
{
vec2 corrected_uvs = CorrectUVs(pass_uv_coords);
vec3 correct_ratio = normalize(texture_ratio);

colour = GetTexture(pass_id0, corrected_uvs) * correct_ratio.x +
GetTexture(pass_id1, corrected_uvs) * correct_ratio.y +
GetTexture(pass_id2, corrected_uvs) * correct_ratio.z;

if(colour.a == 0)
discard;

UseFakeLighting();
}

最佳答案

默认情况下,从顶点着色器到片段着色器的输出变量使用透视正确插值。如果您不想进行插值,请使用 flat 限定您的变量:

flat out vec3 pass_id0;

有关更多信息,请参阅 GLSL Type Qualifiers 。另请参阅这个问题“flat” qualifier in glsl?

关于opengl - glsl片段着色器如何从每个顶点获取非插值数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36516751/

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