Files
noggit-red/src/noggit/rendering/glsl/terrain_frag.glsl

629 lines
22 KiB
GLSL

// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#version 410 core
layout (std140) uniform lighting
{
vec4 DiffuseColor_FogStart;
vec4 AmbientColor_FogEnd;
vec4 FogColor_FogOn;
vec4 LightDir_FogRate;
vec4 OceanColorLight;
vec4 OceanColorDark;
vec4 RiverColorLight;
vec4 RiverColorDark;
};
layout (std140) uniform overlay_params
{
int draw_shadows;
int draw_lines;
int draw_hole_lines;
int draw_areaid_overlay;
int draw_terrain_height_contour;
int draw_wireframe;
int wireframe_type;
float wireframe_radius;
float wireframe_width;
int draw_impass_overlay;
int draw_paintability_overlay;
int draw_selection_overlay;
vec4 wireframe_color;
int draw_impassible_climb;
int climb_use_output_angle;
int climb_use_smooth_interpolation;
float climb_value;
int draw_vertex_color;
int draw_groundeffectid_overlay;
int draw_groundeffect_layerid_overlay;
int draw_noeffectdoodad_overlay;
int draw_only_normals;
int point_normals_up;
};
struct ChunkInstanceData
{
ivec4 ChunkTextureSamplers;
ivec4 ChunkTextureArrayIDs;
ivec4 ChunkHoles_DrawImpass_TexLayerCount_CantPaint;
ivec4 ChunkTexDoAnim;
ivec4 ChunkTexAnimSpeed;
ivec4 AreaIDColor_Pad2_DrawSelection;
ivec4 ChunkXZ_TileXZ;
ivec4 ChunkTexAnimDir;
// Mists Heightmapping
ivec4 ChunkHeightTextureSamplers;
ivec4 ChunkTextureUVScale;
vec4 ChunkTextureHeightScale;
vec4 ChunkTextureHeightOffset;
vec4 ChunkGroundEffectColor;
// pack 8x8 bools in two ints. Simplified ChunksLayerEnabled to a bool instead of 2 bits id.
// If those modes are mutually exclusive, we can do it in ChunkGroundEffectColor for now.
ivec4 ChunkDoodadsEnabled2_ChunksLayerEnabled2;
};
layout (std140) uniform chunk_instances
{
ChunkInstanceData instances[256];
};
uniform sampler2DArray shadowmap;
uniform sampler2DArray alphamap;
uniform sampler2D stamp_brush;
uniform sampler2DArray textures[11];
uniform vec3 camera;
uniform int draw_cursor_circle;
uniform vec3 cursor_position;
uniform float cursorRotation;
uniform float outer_cursor_radius;
uniform float inner_cursor_ratio;
uniform vec4 cursor_color;
uniform bool enable_mists_heightmapping;
in vec3 vary_position;
in vec2 vary_texcoord;
in vec2 vary_t0_uv;
in vec2 vary_t1_uv;
in vec2 vary_t2_uv;
in vec2 vary_t3_uv;
in vec3 vary_normal;
in vec3 vary_mccv;
flat in int instanceID;
flat in vec3 triangle_normal;
out vec4 out_color;
const float TILESIZE = 533.33333;
const float CHUNKSIZE = TILESIZE / 16.0;
const float HOLESIZE = CHUNKSIZE * 0.25;
const float UNITSIZE = HOLESIZE * 0.5;
const float PI = 3.14159265358979323846;
vec3 random_color(float areaID)
{
float r = fract(sin(dot(vec2(areaID), vec2(12.9898, 78.233))) * 43758.5453);
float g = fract(sin(dot(vec2(areaID), vec2(11.5591, 70.233))) * 43569.5451);
float b = fract(sin(dot(vec2(areaID), vec2(13.1234, 76.234))) * 43765.5452);
return vec3(r, g, b);
}
vec4 get_tex_color(vec2 tex_coord, int tex_sampler, int array_index)
{
if (tex_sampler == 0)
{
return texture(textures[0], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 1)
{
return texture(textures[1], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 2)
{
return texture(textures[2], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 3)
{
return texture(textures[3], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 4)
{
return texture(textures[4], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 5)
{
return texture(textures[5], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 6)
{
return texture(textures[6], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 7)
{
return texture(textures[7], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 8)
{
return texture(textures[8], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 9)
{
return texture(textures[9], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 10)
{
return texture(textures[10], vec3(tex_coord, array_index)).rgba;
}
return vec4(0);
/*
// This should be more compliant to the GLSL standard, but seems to be slower :(
vec2 uvDx = dFdx(tex_coord);
vec2 uvDy = dFdy(tex_coord);
vec3 uv = vec3(tex_coord, array_index);
switch(tex_sampler)
{
case 0:
return textureGrad(textures[0], uv, uvDx, uvDy);
case 1:
return textureGrad(textures[1], uv, uvDx, uvDy);
case 2:
return textureGrad(textures[2], uv, uvDx, uvDy);
case 3:
return textureGrad(textures[3], uv, uvDx, uvDy);
case 4:
return textureGrad(textures[4], uv, uvDx, uvDy);
case 5:
return textureGrad(textures[5], uv, uvDx, uvDy);
case 6:
return textureGrad(textures[6], uv, uvDx, uvDy);
case 7:
return textureGrad(textures[7], uv, uvDx, uvDy);
case 8:
return textureGrad(textures[8], uv, uvDx, uvDy);
case 9:
return textureGrad(textures[9], uv, uvDx, uvDy);
case 10:
return textureGrad(textures[10], uv, uvDx, uvDy);
default:
return vec4(0.0);
}
*/
}
const int numChunks = 16;
const int numTiles = 64;
vec2 getAdjustedUV(vec2 uv, int textureScale) {
vec2 worldOffset = (numChunks * instances[instanceID].ChunkXZ_TileXZ.zw) + instances[instanceID].ChunkXZ_TileXZ.xy;
// Scale the UV coordinates. Wow Interprets texture scaling this way.
vec2 combinedUV = fract((uv + worldOffset) / ((1 << textureScale) / 8.0f));
return combinedUV;
}
vec4 mists_texture_blend()
{
vec3 alpha = texture(alphamap, vec3(vary_texcoord / 8.0, instanceID)).rgb;
int layer_count = instances[instanceID].ChunkHoles_DrawImpass_TexLayerCount_CantPaint.b;
alpha.r = mix(alpha.r, 0.0, float(layer_count < 2));
alpha.g = mix(alpha.g, 0.0, float(layer_count < 3));
alpha.b = mix(alpha.b, 0.0, float(layer_count < 4));
vec2 worldScaled_vary_t0_uv = getAdjustedUV(vary_t0_uv/8.0, instances[instanceID].ChunkTextureUVScale.x);
vec2 worldScaled_vary_t1_uv = getAdjustedUV(vary_t1_uv/8.0, instances[instanceID].ChunkTextureUVScale.y);
vec2 worldScaled_vary_t2_uv = getAdjustedUV(vary_t2_uv/8.0, instances[instanceID].ChunkTextureUVScale.z);
vec2 worldScaled_vary_t3_uv = getAdjustedUV(vary_t3_uv/8.0, instances[instanceID].ChunkTextureUVScale.w);
// Mists HeightMapping: Multi Layer Blending.
vec4 layer_weights = vec4(1.0 - clamp(dot(vec3(1.0),alpha), 0, 1), alpha);
vec4 t0h = get_tex_color(worldScaled_vary_t0_uv, instances[instanceID].ChunkHeightTextureSamplers.x, abs(instances[instanceID].ChunkTextureArrayIDs.x));
vec4 t1h = get_tex_color(worldScaled_vary_t1_uv, instances[instanceID].ChunkHeightTextureSamplers.y, abs(instances[instanceID].ChunkTextureArrayIDs.y));
vec4 t2h = get_tex_color(worldScaled_vary_t2_uv, instances[instanceID].ChunkHeightTextureSamplers.z, abs(instances[instanceID].ChunkTextureArrayIDs.z));
vec4 t3h = get_tex_color(worldScaled_vary_t3_uv, instances[instanceID].ChunkHeightTextureSamplers.w, abs(instances[instanceID].ChunkTextureArrayIDs.w));
vec4 layer_pct = vec4 ( layer_weights.x * ( t0h.a * instances[instanceID].ChunkTextureHeightScale.x + instances[instanceID].ChunkTextureHeightOffset.x)
, layer_weights.y * ( t1h.a * instances[instanceID].ChunkTextureHeightScale.y + instances[instanceID].ChunkTextureHeightOffset.y)
, layer_weights.z * ( t2h.a * instances[instanceID].ChunkTextureHeightScale.z + instances[instanceID].ChunkTextureHeightOffset.z)
, layer_weights.w * ( t3h.a * instances[instanceID].ChunkTextureHeightScale.w + instances[instanceID].ChunkTextureHeightOffset.w)
);
vec4 layer_pct_max = vec4( max( max(layer_pct.x, layer_pct.y) , max(layer_pct.z, layer_pct.w) ) );
layer_pct = layer_pct * (vec4(1.0) - clamp(layer_pct_max - layer_pct, 0, 1));
layer_pct = layer_pct / vec4( dot(vec4(1.0),layer_pct) );
vec4 t0 = get_tex_color(worldScaled_vary_t0_uv, instances[instanceID].ChunkTextureSamplers.x,
abs(instances[instanceID].ChunkTextureArrayIDs.x)) * layer_pct.x;
t0.a = mix(t0.a, 0.f, int(instances[instanceID].ChunkTextureArrayIDs.x < 0));
vec4 t1 = get_tex_color(worldScaled_vary_t1_uv, instances[instanceID].ChunkTextureSamplers.y,
abs(instances[instanceID].ChunkTextureArrayIDs.y)) * layer_pct.y;
//vec4 t1 = get_tex_color(vary_t1_uv / 5 , instances[instanceID].ChunkTextureSamplers.y, abs(instances[instanceID].ChunkTextureArrayIDs.y));
t1.a = mix(t1.a, 0.f, int(instances[instanceID].ChunkTextureArrayIDs.y < 0));
vec4 t2 = get_tex_color(worldScaled_vary_t2_uv, instances[instanceID].ChunkTextureSamplers.z,
abs(instances[instanceID].ChunkTextureArrayIDs.z)) * layer_pct.z;
t2.a = mix(t2.a, 0.f, int(instances[instanceID].ChunkTextureArrayIDs.z < 0));
vec4 t3 =get_tex_color(worldScaled_vary_t3_uv, instances[instanceID].ChunkTextureSamplers.w,
abs(instances[instanceID].ChunkTextureArrayIDs.w)) * layer_pct.w;
t3.a = mix(t3.a, 0.f, int(instances[instanceID].ChunkTextureArrayIDs.w < 0));
return vec4 (t0 + t1 + t2 + t3);//(t0 * (1.0 - (a0 + a1 + a2)) + t1 * a0 + t2 * a1 + t3 * a2);
}
vec4 texture_blend()
{
vec3 alpha = texture(alphamap, vec3(vary_texcoord / 8.0, instanceID)).rgb;
int layer_count = instances[instanceID].ChunkHoles_DrawImpass_TexLayerCount_CantPaint.b;
alpha.r = mix(alpha.r, 0.0, float(layer_count < 2));
alpha.g = mix(alpha.g, 0.0, float(layer_count < 3));
alpha.b = mix(alpha.b, 0.0, float(layer_count < 4));
float a0 = alpha.r;
float a1 = alpha.g;
float a2 = alpha.b;
vec4 t0 = get_tex_color(vary_t0_uv, instances[instanceID].ChunkTextureSamplers.x, abs(instances[instanceID].ChunkTextureArrayIDs.x));
t0.a = mix(t0.a, 0.f, int(instances[instanceID].ChunkTextureArrayIDs.x < 0));
vec4 t1 = get_tex_color(vary_t1_uv, instances[instanceID].ChunkTextureSamplers.y, abs(instances[instanceID].ChunkTextureArrayIDs.y));
t1.a = mix(t1.a, 0.f, int(instances[instanceID].ChunkTextureArrayIDs.y < 0));
vec4 t2 = get_tex_color(vary_t2_uv, instances[instanceID].ChunkTextureSamplers.z, abs(instances[instanceID].ChunkTextureArrayIDs.z));
t2.a = mix(t2.a, 0.f, int(instances[instanceID].ChunkTextureArrayIDs.z < 0));
vec4 t3 = get_tex_color(vary_t3_uv, instances[instanceID].ChunkTextureSamplers.w, abs(instances[instanceID].ChunkTextureArrayIDs.w));
t3.a = mix(t3.a, 0.f, int(instances[instanceID].ChunkTextureArrayIDs.w < 0));
return vec4 (t0 * (1.0 - (a0 + a1 + a2)) + t1 * a0 + t2 * a1 + t3 * a2);
}
float contour_alpha(float unit_size, float pos, float line_width)
{
float f = abs(fract((pos + unit_size*0.5) / unit_size) - 0.5);
float df = abs(line_width / unit_size);
return smoothstep(0.0, df, f);
}
float contour_alpha(float unit_size, vec2 pos, vec2 line_width)
{
return 1.0 - min( contour_alpha(unit_size, pos.x, line_width.x)
, contour_alpha(unit_size, pos.y, line_width.y)
);
}
void main()
{
float dist_from_camera = distance(camera, vary_position);
vec3 fw = fwidth(vary_position.xyz);
// calc world lighting
vec3 currColor;
vec3 lDiffuse = vec3(0.0, 0.0, 0.0);
// vec3 accumlatedLight = vec3(1.0, 1.0, 1.0);
vec3 normalized_normal = normalize(vary_normal);
if(point_normals_up == 1)
{
normalized_normal = vec3(0, 1, 0);
}
float nDotL = clamp(dot(normalized_normal, -normalize(LightDir_FogRate.xyz)), 0.0, 1.0); // default LightDir = -0.6
vec3 skyColor = (AmbientColor_FogEnd.xyz * 1.10000002);
vec3 groundColor = (AmbientColor_FogEnd.xyz * 0.699999988);
currColor = mix(groundColor, skyColor, 0.5 + (0.5 * nDotL));
lDiffuse = DiffuseColor_FogStart.xyz * nDotL;
vec3 reflection = normalize(normalized_normal - (-LightDir_FogRate.xyz));
float specularFactor = max(dot(reflection, normalize(camera - vary_position)), 0.0);
// blend textures
if(enable_mists_heightmapping)
{
out_color = mix(vec4(1.0, 1.0, 1.0, 0.0), mists_texture_blend(), int(instances[instanceID].ChunkHoles_DrawImpass_TexLayerCount_CantPaint.b > 0));
}
else
{
out_color = mix(vec4(1.0, 1.0, 1.0, 0.0), texture_blend(), int(instances[instanceID].ChunkHoles_DrawImpass_TexLayerCount_CantPaint.b > 0));
}
vec3 spc = out_color.a * out_color.rgb * pow(specularFactor, 8);
out_color.a = 1.0;
// apply vertex color
if (draw_vertex_color != 0)
{
out_color.rgb *= vary_mccv;
}
// apply world lighting
out_color.rgb = clamp(out_color.rgb * (currColor + lDiffuse + spc), 0.0, 1.0);
// apply overlays
if(draw_paintability_overlay != 0 && instances[instanceID].ChunkHoles_DrawImpass_TexLayerCount_CantPaint.a != 0)
{
out_color *= vec4(1.0, 0.0, 0.0, 1.0);
}
if(draw_areaid_overlay != 0)
{
out_color.rgb = out_color.rgb * 0.3 + random_color(instances[instanceID].AreaIDColor_Pad2_DrawSelection.r);
}
if(draw_groundeffectid_overlay != 0)
{
out_color.rgb = out_color.rgb * 0.3 + instances[instanceID].ChunkGroundEffectColor.rgb;
}
if(draw_groundeffect_layerid_overlay != 0)
{
// if chuck does not have our texture it is set as black color
if (instances[instanceID].ChunkGroundEffectColor.rgb == vec3(0.0, 0.0, 0.0))
{
out_color.rgb = out_color.rgb * 0.3 + instances[instanceID].ChunkGroundEffectColor.rgb;
}
else
{
uint is_active = 0;
uvec2 tile_index = uvec2(uint(floor(vary_position.x / TILESIZE)), uint(floor(vary_position.z / TILESIZE)));
vec2 tile_base_pos = vec2(float(tile_index.x * TILESIZE), float(tile_index.y * TILESIZE));
uvec2 chunk_index = uvec2(uint(floor(instanceID / 16)), uint(floor(instanceID % 16)));
vec2 chunk_base_pos = vec2(float(chunk_index.x * CHUNKSIZE), float(chunk_index.y * CHUNKSIZE));
uint unit_x = uint(floor((vary_position.x - (tile_base_pos.x + chunk_base_pos.x)) / UNITSIZE));
uint unit_z = uint(floor((vary_position.z - (tile_base_pos.y + chunk_base_pos.y)) / UNITSIZE));
// x and y aren't swapped because getDoodadActiveLayerIdAt() already does it in code
if (unit_x < 4)
{
is_active = uint(instances[instanceID].ChunkDoodadsEnabled2_ChunksLayerEnabled2.b) & (1 << ((unit_x * 8) + unit_z) );
}
else
{
is_active = uint(instances[instanceID].ChunkDoodadsEnabled2_ChunksLayerEnabled2.a) & (1 << ((unit_x * 8) + unit_z) - 32 ); // (unit_x-4) * 8 + unit_z)
}
if (is_active != 0)
{
// if set, draw chunk in green
out_color.rgb = mix(vec3(0.0, 1.0, 0.0), out_color.rgb, 0.7);
}
else
{
// else, draw in red
out_color.rgb = mix(vec3(1.0, 0.0, 0.0), out_color.rgb, 0.7);
}
}
}
// render mode for ge doodads enabled on chunk unit. no_render set = white
if(draw_noeffectdoodad_overlay != 0)
{
uint no_doodad = 0;
uvec2 tile_index = uvec2(uint(floor(vary_position.x / TILESIZE)), uint(floor(vary_position.z / TILESIZE)));
vec2 tile_base_pos = vec2(float(tile_index.x * TILESIZE), float(tile_index.y * TILESIZE));
uvec2 chunk_index = uvec2(uint(floor(instanceID / 16)), uint(floor(instanceID % 16)));
// uint chunk_x = uint(floor( (vary_position.x - tile_base_pos.x) / CHUNKSIZE));
// uint chunk_y = uint(floor( (vary_position.z - tile_base_pos.y) / CHUNKSIZE));
vec2 chunk_base_pos = vec2(float(chunk_index.x * CHUNKSIZE), float(chunk_index.y * CHUNKSIZE));
uint unit_x = uint(floor((vary_position.x - (tile_base_pos.x + chunk_base_pos.x)) / UNITSIZE));
uint unit_z = uint(floor((vary_position.z - (tile_base_pos.y + chunk_base_pos.y)) / UNITSIZE));
// swapped x and y order, the data is wrongly ordered when loaded
if (unit_z < 4)
{
no_doodad = uint(instances[instanceID].ChunkDoodadsEnabled2_ChunksLayerEnabled2.r) & (1 << ((unit_z * 8) + unit_x) );
}
else
{
no_doodad = uint(instances[instanceID].ChunkDoodadsEnabled2_ChunksLayerEnabled2.g) & (1 << ((unit_z * 8) + unit_x) - 32 ); // (unit_x-4) * 8 + unit_z)
}
if (no_doodad != 0)
{
// if set, draw chunk in white
out_color.rgb = mix(vec3(1.0), out_color.rgb, 0.5);
}
else
{
// else, draw in black(default)
out_color.rgb = mix(vec3(0.0), out_color.rgb, 0.5);
}
}
if(draw_impass_overlay != 0 && instances[instanceID].ChunkHoles_DrawImpass_TexLayerCount_CantPaint.g != 0)
{
out_color.rgb = mix(vec3(1.0), out_color.rgb, 0.5);
}
if(draw_selection_overlay != 0 && instances[instanceID].AreaIDColor_Pad2_DrawSelection.a != 0)
{
out_color.rgb = mix(vec3(1.0), out_color.rgb, 0.5);
}
if (draw_shadows != 0)
{
float shadow_alpha = texture(shadowmap, vec3(vary_texcoord / 8.0, instanceID)).r;
out_color = vec4 (out_color.rgb * (1.0 - shadow_alpha), 1.0);
}
if (draw_terrain_height_contour != 0)
{
out_color = vec4(out_color.rgb * contour_alpha(4.0, vary_position.y+0.1, fw.y), 1.0);
}
bool lines_drawn = false;
if(draw_lines != 0)
{
vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
color.a = contour_alpha(TILESIZE, vary_position.xz, fw.xz * 1.5);
color.g = color.a > 0.0 ? 0.8 : 0.0;
if(color.a == 0.0)
{
color.a = contour_alpha(CHUNKSIZE, vary_position.xz, fw.xz);
color.r = color.a > 0.0 ? 0.8 : 0.0;
}
if(draw_hole_lines != 0 && color.a == 0.0)
{
color.a = contour_alpha(HOLESIZE, vary_position.xz, fw.xz * 0.75);
color.b = 0.8;
}
lines_drawn = color.a > 0.0;
out_color.rgb = mix(out_color.rgb, color.rgb, color.a);
}
if(FogColor_FogOn.w != 0)
{
float start = AmbientColor_FogEnd.w * DiffuseColor_FogStart.w; // 0
vec3 fogParams;
fogParams.x = -(1.0 / (AmbientColor_FogEnd.w - start)); // - 1 / 338
fogParams.y = (1.0 / (AmbientColor_FogEnd.w - start)) * AmbientColor_FogEnd.w; // 1 / 338 * 338
fogParams.z = LightDir_FogRate.w; // 2.7
float f1 = (dist_from_camera * fogParams.x) + fogParams.y; // 1.0029
float f2 = max(f1, 0.0);
float f3 = pow(f2, fogParams.z);
float f4 = min(f3, 1.0);
float fogFactor = 1.0 - f4;
float alpha = clamp((dist_from_camera - start) / (AmbientColor_FogEnd.w - start), 0.0, 1.0);
out_color.rgb = mix(out_color.rgb, FogColor_FogOn.rgb, fogFactor);
}
if(draw_wireframe != 0 && !lines_drawn)
{
// true by default => type 0
bool draw_wire = true;
float real_wireframe_radius = max(outer_cursor_radius * wireframe_radius, 2.0 * UNITSIZE);
if(wireframe_type == 1)
{
draw_wire = (length(vary_position.xz - cursor_position.xz) < real_wireframe_radius);
}
if(draw_wire)
{
float alpha = contour_alpha(UNITSIZE, vary_position.xz, fw.xz * wireframe_width);
float xmod = mod(vary_position.x, UNITSIZE);
float zmod = mod(vary_position.z, UNITSIZE);
float d = length(fw.xz) * wireframe_width;
float diff = min( min(abs(xmod - zmod), abs(xmod - UNITSIZE + zmod))
, min(abs(zmod - xmod), abs(zmod + UNITSIZE - zmod))
);
alpha = max(alpha, 1.0 - smoothstep(0.0, d, diff));
out_color.rgb = mix(out_color.rgb, wireframe_color.rgb, wireframe_color.a *alpha);
}
}
if (draw_impassible_climb != 0)
{
vec4 color = vec4(out_color.r, out_color.g, out_color.b, 0.5);
vec3 use_normal;
if (climb_use_smooth_interpolation != 0)
{
use_normal = vary_normal;
}
else
{
use_normal = triangle_normal;
}
float d1 = use_normal.y;
float d2 = sqrt(use_normal.x * use_normal.x +
use_normal.y * use_normal.y +
use_normal.z * use_normal.z);
if (d2 > 0.0)
{
float normal_angle = acos(d1/d2);
if (climb_use_output_angle != 0)
{
color.r = normal_angle;
}
else
{
if (normal_angle > climb_value)
{
color.r = 1.0;
}
}
}
out_color.rgb = mix(out_color.rgb, color.rgb, color.a);
}
if(draw_cursor_circle == 1)
{
float diff = length(vary_position.xz - cursor_position.xz);
diff = min(abs(diff - outer_cursor_radius), abs(diff - outer_cursor_radius * inner_cursor_ratio));
float alpha = smoothstep(0.0, length(fw.xz), diff);
out_color.rgb = mix(cursor_color.rgb, out_color.rgb, alpha);
}
else if(draw_cursor_circle == 2)
{
float angle = cursorRotation * 2.0 * PI;
vec2 topleft = cursor_position.xz;
topleft.x -= outer_cursor_radius;
topleft.y -= outer_cursor_radius;
vec2 texcoord = (vary_position.xz - topleft) / outer_cursor_radius * 0.5 - 0.5;
vec2 rotatedTexcoord;
rotatedTexcoord.x = texcoord.x * cos(angle) + texcoord.y * sin(angle) + 0.5;
rotatedTexcoord.y = texcoord.y * cos(angle) - texcoord.x * sin(angle) + 0.5;
/*out_color.rgb = mix(out_color.rgb, texture(stampBrush, rotatedTexcoord).rgb
, 1.0 * (int(length(vary_position.xz - cursor_position.xz) / outer_cursor_radius < 1.0))
* (1.0 - length(vary_position.xz - cursor_position.xz) / outer_cursor_radius));*/
out_color.rgb = mix(out_color.rgb, cursor_color.rgb, texture(stamp_brush, rotatedTexcoord).r
* int(abs(vary_position.x - cursor_position.x) <= outer_cursor_radius
&& abs(vary_position.z - cursor_position.z) <= outer_cursor_radius));
/*vec2 posRel = vary_position.xz - cursor_position.xz;
float pos_x = posRel.x * sin(angle) - posRel.y * cos(angle);
float pos_z = posRel.y * sin(angle) + posRel.x * cos(angle);
float diff_x = abs(pos_x);
float diff_z = abs(pos_z);
float inner_radius = outer_cursor_radius * inner_cursor_ratio;
float d = length(fw);
float alpha = 1.0 * (1 - int((diff_x < outer_cursor_radius && diff_z < outer_cursor_radius
&& (outer_cursor_radius - diff_x <= d || outer_cursor_radius - diff_z <= d)) || (diff_x < inner_radius
&& diff_z < inner_radius && (inner_radius - diff_x <= d || inner_radius - diff_z <= d))));
out_color.rgb = mix(cursor_color.rgb, out_color.rgb, alpha);*/
}
if(draw_only_normals != 0)
{
out_color.rgb = vec3(vary_normal.z * -1, vary_normal.y, vary_normal.x * -1) * 0.5 + 0.5;
}
}