Pull to refresh

Comments 27

Оригинальный шейдер является частью коммерческого проекта, поэтому его исходников не будет.
Но если вы хотите повторить эксперимент в Unity 3D, то создайте сцену с плоскостью и назначьте ей следующий шейдер:
Код шейдера из статьи
Shader "Custom/Demo" {
	Properties {
		_Tex1 ("Texture 1 (RGB) Depth (A)", 2D) = "white" {}
		_Tex2 ("Texture 2 (RGB) Depth (A)", 2D) = "white" {}
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		CGPROGRAM
		#pragma surface surf Lambert

		sampler2D _Tex1;
		sampler2D _Tex2;

		struct Input {
			float2 uv_Tex1;
			float2 uv_Tex2;
		};

		float3 blend(float4 texture1, float a1, float4 texture2, float a2)
		{
			float depth = 0.2;
			float ma = max(texture1.a + a1, texture2.a + a2) - depth;
			float b1 = max(texture1.a + a1 - ma, 0);
			float b2 = max(texture2.a + a2 - ma, 0);
			return (texture1.rgb * b1 + texture2.rgb * b2) / (b1 + b2);
		}

		void surf (Input IN, inout SurfaceOutput o) {
			half4 c1 = tex2D (_Tex1, IN.uv_Tex1);
			half4 c2 = tex2D (_Tex2, IN.uv_Tex2);
			o.Albedo = blend(c1, IN.uv_Tex2.x, c2, 1 - IN.uv_Tex2.x);
		}
		ENDCG
	} 
	FallBack "Diffuse"
}

Как это разширяется на >2 леера?
Филлрейт явно сильно выше (особенно если надо еще и нормалмапы смешивать)

Но решение интересное

Как это разширяется на >2 леера?
Последовательно расширяется. Смешали 2 компоненты — результат смешиваем с третьей. Поскольку максимум — ассоциативная и коммутативная функция, порядок не важен.
Очень просто. Добавьте еще один слой в графики:)
Или, как уже заметил mayorovp, последовательное расширение.



В шейдере для своей игрушки я смешиваю 4 разных текстуры вместе с картами нормалей и одну карту шума.
После игр с математическими операциями мне даже удалось уложиться в ограничения SM2.0.
Тоесть для 3ех лееров это будет выглядеть вот так?

float3 blend(float4 texture1, float a1, float4 texture2, float a2,float4 texture3, float a3)
{
    float depth = 0.2;
    float ma = max(max(texture1.a + a1, texture2.a + a2),texture3.a + a3) - depth;

    float b1 = max(texture1.a + a1 - ma, 0);
    float b2 = max(texture2.a + a2 - ma, 0);
    float b3 = max(texture3.a + a3 - ma, 0);

    return (texture1.rgb * b1 + texture2.rgb * b2+texture3.rgb * b3) / (b1 + b2+b3);
}
Филрейт будет больше относительно какого метода?
float3 blend(float4 texture1, float a1, float4 texture2, float a2) { return texture1.a > texture2.a ? texture1.rgb : texture2.rgb; }
texture1.a и texture2.a — это что за переменная? откуда берется?
texture1 и texture2 — это цвета пикселя на текстуре. В коде вызовы texture2D убраны.
Красиво, но ?: в шейдере? Как так можно?
// второй шейдер
mix(texture1.rgb, texture2.rgb, step(texture1.a, texture2.a));
// третий шейдер
mix(texture1.rgb, texture2.rgb, step(texture1.a + a1, texture2.a + a2));
В основном для наглядности, в конечном шейдере нет условных переходов.

Не вижу mix в Cg, наверно lerp?
Увидев картинку в шапке, рассчитывал на статью побольше.

Допустим нам надо сделать такой методикой островок камушков посреди песка. Как с этим справиться, используя Ваш алгоритм?
То, что Вы показали очень частный случай и в нем-то всё хорошо, красиво и просто. Мой вопрос связан, по сути, с непосредственным использованием Вашего алгоритма на практике. Давайте для простоты решим что мы делаем стратегию в 2д.
Шейдер как раз и разрабатывался для изометрической 2D стратегии.
С островками никаких проблем нет, мы просто рисуем их на карте прозрачности слоев.
Карта прозрачности



Тоесть карту прозрачности готовите заранее, или на лету делаете?
Карта прозрачности готовится прямо в Unity в самописном редакторе.
Но она легко может меняться даже непосредственно в игре.
Может быть тогда стоит написать в начале статьи, что код и реализация на Unity?

Мне вот, как разработчику под собственный фреймворк, и пишущем на hlsl этот код шейдера немного непривычен :)
В начале я даже было подумал что это псевдокод шейдера.
Я старался сделать упор именно на алгоритме, а не на конкретной реализации.
Это не целые шейдеры же, а только одна функция. А Cg и HLSL практическип одинаковы.
А если заменить float3 на vec3 и float4 на vec4 (или написать #define float3 vec3 и #define float4 vec4), получится GLSL.
Я никогда графикой не занимался, поэтому прошу прощения, если вопрос тривиальный.
Откуда Вы получили карту высот? Сгенерировали автоматически из текстур? Сделали руками «на глаз»? Или она была получена при генерировании текстуры?
В данном примере я сгенерировал ее из самой текстуры в оттенках серого и поместил в альфа-канал.

Думаю речь идет о использовании информации о яркости пикселя.
Круто! Идею понял, возьму себе на заметку… если вдруг буду что-то писать.
Sign up to leave a comment.

Articles