#c# #winforms #opengl #glsl #opentk
#c# #winforms #opengl #glsl #opentk
Вопрос:
Мне удалось создать хорошо освещенную сцену с помощью OpenGL (OpenTK, потому что я использую C # и Winforms), используя следующий шейдер фрагментов:
#version 420 core
in vec3 FragPos;
in vec3 Normal;
in vec2 texCoord;
out vec4 FragColor;
uniform sampler2D texture0;
uniform sampler2D texture1;
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform Material material;
uniform Light light;
uniform vec3 viewPos;
void main()
{
// Ambient
vec3 ambient = light.ambient * vec3(texture(material.diffuse, texCoord));
// Diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(vec3(light.position - FragPos));
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, texCoord));
// Specular
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * spec * vec3(texture(material.specular, texCoord));
vec3 result = ambient diffuse specular;
FragColor = vec4(result, 1.0);
}
К сожалению, это решение, похоже, не учитывает альфа-канал текстур. В результате получается такая сцена:
План состоит в том, что левая сфера — это облачный слой. Текстура содержит альфа-канал, который должен привести к прозрачной сфере с видимыми облаками. Не путайте: облачная сфера будет перемещена обратно над землей, когда все снова заработает.
Прежде чем я реализовал окружающее, рассеянное и зеркальное освещение, я использовал следующий шейдер фрагментов:
#version 420 core
in vec2 texCoord;
out vec4 FragColor;
uniform sampler2D texture0;
uniform sampler2D texture1;
void main()
{
vec4 outputColor = mix(texture(texture0, texCoord), texture(texture1, texCoord), 0.2);
if(outputColor.a < 0.1)
discard;
FragColor = outputColor;
}
Этот шейдер учитывает альфа-канал, и он работал так, как предполагалось. Важно сказать, что облака и земля являются отдельными объектами сферы. texture1 в старом шейдере вообще не используется. Итак, единственной релевантной текстурой является texture0.
Итак, «целью» должно быть добавление альфа-канала в новый шейдер (тот, у которого есть освещение).
Извините, если этот вопрос кажется вам глупым. Я новичок в OpenGL и все еще учусь. Заранее спасибо!
Ответ №1:
У вас должны быть mix
текстуры, зависящие от альфа-канала облачного слоя. Предположим, что «texture1» — это облачный слой:
vec4 groundColor = texture(texture0, texCoord);
vec4 cloudColor = texture(texture1, texCoord);
vec4 outputColor = vec4(mix(grundColor.rgb, cloudColor.rgb, cloudColor.a), 1.0);
FragColor = outputColor;
Комментарии:
1. Привет, спасибо за ваш ответ. Я забыл упомянуть кое-что в объяснении (я добавлю это сейчас): облака и земля — это отдельные объекты сферы. texture1 в старом шейдере вообще не используется. Итак, единственной релевантной текстурой является texture0.
2. @BanditBloodwyn я в замешательстве и понятия не имею, чего ты хочешь. У вас есть 2 прохода, один для земли и один для облаков? Используете ли вы один и тот же шейдер для обоих проходов? Смешивание не достигается в программе шейдеров. Смешивание — это этап, и его необходимо включить. Прочитайте Blening .
3. Чтобы упростить: я почти уверен, что мой шейдер (первый здесь) не поддерживает альфа-смешивание, потому что альфа-канал не учитывается. Я вижу важное различие между старым шейдером и новым: старый дает FragColor vec4 (RGBA), а новый — vec3 (RGB) 1.0 в качестве четвертого для создания vec4. Итак, вопрос в том, как повторно включить четвертый канал (альфа) вместо использования только 1.0? Надеюсь, теперь это понятно
Ответ №2:
Я нашел решение самостоятельно. Здесь исправлен шейдер:
#version 420 core
in vec3 FragPos;
in vec3 Normal;
in vec2 texCoord;
out vec4 FragColor;
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform Material material;
uniform Light light;
uniform vec3 viewPos;
void main()
{
// Ambient
vec4 ambient = vec4(light.ambient, 1.0) * texture(material.diffuse, texCoord);
// Diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(vec3(light.position - FragPos));
float diff = max(dot(norm, lightDir), 0.0);
vec4 diffuse = vec4(light.diffuse, 1.0) * diff * texture(material.diffuse, texCoord);
// Specular
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec4 specular = vec4(light.specular, 1.0) * spec * texture(material.specular, texCoord);
vec4 result = ambient diffuse specular;
if(result.a < 0.1)
discard;
FragColor = resu<
}
Если у вас есть идея получше, я был бы рад попробовать ее 🙂