2012-04-02 2 views
0

Допустим, мы текстурируем квадрат (два треугольника). Я думаю, что этот вопрос похож на текстуру splatting, как в следующем примереGLSL текстура смешивания с текстурой деколя в нужном месте

precision lowp float; 

uniform sampler2D Terrain; 
uniform sampler2D Grass; 
uniform sampler2D Stone; 
uniform sampler2D Rock; 

varying vec2 tex_coord; 

void main(void) 
{ 
vec4 terrain = texture2D(Terrain, tex_coord); 
vec4 tex0 = texture2D(Grass, tex_coord * 4.0); // Tile 
vec4 tex1 = texture2D(Rock, tex_coord * 4.0); // Tile 
vec4 tex2 = texture2D(Stone, tex_coord * 4.0); // Tile 

tex0 *= terrain.r; // Red channel - puts grass 
tex1 = mix(tex0, tex1, terrain.g); // Green channel - puts rock and mix with grass 
vec4 outColor = mix(tex1, tex2, terrain.b); // Blue channel - puts stone and mix with others 

gl_FragColor = outColor; //final color 
} 

Но я хочу просто поместить 1 наклейку на базовую текстуре четырехъядерной в желаемом месте.
Алгоритм такой же, но я думаю, что нам не нужна дополнительная текстура с 1 заполненным слоем для удержания позиций (например, где красный слой! = 0) наклейки, некоторые из них должны генерировать наш собственный «terrain.r» (это плавающая?) переменная, а также текстура смешивания и текстура деколя с ней.

precision lowp float; 

uniform sampler2D base; 
uniform sampler2D decal; 
uniform vec2 decal_location; //where we want place decal (e.g. 0.5, 0.5 is center of quad) 

varying vec2 base_tex_coord; 
varying vec2 decal_tex_coord; 

void main(void) 
{ 
vec4 v_base = texture2D(base, base_tex_coord); 
vec4 v_decal = texture2D(Grass, decal_tex_coord); 
float decal_layer = /*somehow get our decal_layer based on decal_position*/ 

gl_FragColor = mix(v_base, v_decal, decal_layer); 
} 

Как достичь такой цели?
Или я могу просто создать текстуру splat на стороне opengl и передать ее в первый шейдер? Это даст мне до 4-х различных наклейках на квад, но будет медленным для частых обновлений (например, пулемёт хитов стены)

ответ

1

Да, decal_layer - это поплавок, как вы описали. Его диапазон от 0 до 1. Но у вас недостаточно информации, здесь вы указали decal_location, но не размер для декали. Вы также не знаете, где этот фрагмент попадает в квад, вам понадобится varying vec2 quad_coord; или аналогичный ввод из вершинного шейдера, если вы хотите знать, где этот фрагмент относится к отображаемому квадруму.

Но давайте попробуем другой подход. Изменение верхней части вашего 2-го, например, чтобы включить эти формы:

uniform vec2 decal_location; // Location of decal relative to base_tex_coord uniform float decal_size; // Size of decal relative to base_tex_coord

Теперь, в основной(), вы должны быть в состоянии вычислить decal_layer с чем-то вроде этого:

float decal_layer = 1.0 - smoothstep(decal_size - 0.01, decal_size, max(abs(decal_location.x - base_tex_coord.x), abs(decal_location.y - base_tex_coord.y)));

В основном вы пытаетесь получить файл decal_layer равным 1.0 в пределах надписи, а 0.0 вне деколя. Я добавил на границу, на которую вы можете играть, нечеткое грани 0.01. Удачи!

2
float decal_layer = /*somehow get our decal_layer based on decal_position*/ 

Ну, это до вас, как вы интерпретируете decal_position. Я думаю, что достаточно простой метрики расстояния. но для этого также требуется размер размера. Предположим, вы предоставили это через дополнительный равномерный decal_radius. Затем мы можем использовать

decal_layer = clamp(length(decal_position - vec2(0.5, 0.5))/decal_radius, 0., 1.); 
+0

Твой тоже хорошо, только 30,8 тыс. Больше, чем 66, новичкам нужна помощь новичку. – Aristarhys

Смежные вопросы