render quad sprites in full resolution
This commit is contained in:
parent
2dd15d1078
commit
c26488870a
@ -1915,7 +1915,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
Affine wep_uv_to_world_af = ScaleAffine(wep_pix_to_world_af, DimsFromRng2(wep.tex_rect));
|
||||
|
||||
V_Quad *quad = PushStruct(frame->quads_arena, V_Quad);
|
||||
quad->quad_uv_to_shade_af = MulAffine(frame->af.world_to_shade, wep_uv_to_world_af);
|
||||
quad->quad_uv_to_screen_af = MulAffine(frame->af.world_to_screen, wep_uv_to_world_af);
|
||||
quad->tex = wep.tex;
|
||||
quad->tex_slice_uv = DivRng2Vec2(wep.tex_rect, wep.tex_dims);
|
||||
}
|
||||
@ -1926,7 +1926,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
Affine body_uv_to_world_af = ScaleAffine(body_pix_to_world_af, DimsFromRng2(body.tex_rect));
|
||||
|
||||
V_Quad *quad = PushStruct(frame->quads_arena, V_Quad);
|
||||
quad->quad_uv_to_shade_af = MulAffine(frame->af.world_to_shade, body_uv_to_world_af);
|
||||
quad->quad_uv_to_screen_af = MulAffine(frame->af.world_to_screen, body_uv_to_world_af);
|
||||
quad->tex = body.tex;
|
||||
quad->tex_slice_uv = DivRng2Vec2(body.tex_rect, body.tex_dims);
|
||||
}
|
||||
@ -4277,6 +4277,16 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
Rng3 screen_viewport = RNG3(VEC3(0, 0, 0), VEC3(frame->screen_dims.x, frame->screen_dims.y, 1));
|
||||
Rng2 screen_scissor = RNG2(VEC2(screen_viewport.p0.x, screen_viewport.p0.y), VEC2(screen_viewport.p1.x, screen_viewport.p1.y));
|
||||
|
||||
// Albedo texture
|
||||
G_ResourceHandle albedo_target = G_PushTexture2D(
|
||||
frame->gpu_arena, frame->cl,
|
||||
G_Format_R16G16B16A16_Float,
|
||||
frame->screen_dims,
|
||||
G_Layout_DirectQueue_RenderTargetWrite,
|
||||
.flags = G_ResourceFlag_AllowRenderTarget
|
||||
);
|
||||
G_Texture2DRef albedo_target_ro = G_PushTexture2DRef(frame->gpu_arena, albedo_target);
|
||||
|
||||
// Shade texture
|
||||
G_ResourceHandle shade_target = G_PushTexture2D(
|
||||
frame->gpu_arena, frame->cl,
|
||||
@ -4290,16 +4300,6 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
Rng3 shade_viewport = RNG3(VEC3(0, 0, 0), VEC3(frame->shade_dims.x, frame->shade_dims.y, 1));
|
||||
Rng2 shade_scissor = RNG2(VEC2(shade_viewport.p0.x, shade_viewport.p0.y), VEC2(shade_viewport.p1.x, shade_viewport.p1.y));
|
||||
|
||||
// Albedo texture
|
||||
G_ResourceHandle albedo_target = G_PushTexture2D(
|
||||
frame->gpu_arena, frame->cl,
|
||||
G_Format_R16G16B16A16_Float,
|
||||
frame->shade_dims,
|
||||
G_Layout_DirectQueue_RenderTargetWrite,
|
||||
.flags = G_ResourceFlag_AllowRenderTarget
|
||||
);
|
||||
G_Texture2DRef albedo_target_ro = G_PushTexture2DRef(frame->gpu_arena, albedo_target);
|
||||
|
||||
// Quad buffers
|
||||
G_ResourceHandle quads_buff = G_PushBufferFromCpuCopy(frame->gpu_arena, frame->cl, StringFromArena(frame->quads_arena));
|
||||
G_StructuredBufferRef quads_ref = G_PushStructuredBufferRef(frame->gpu_arena, quads_buff, V_Quad);
|
||||
@ -4356,9 +4356,9 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
params.shade_dims = frame->shade_dims;
|
||||
params.shade_ro = shade_target_ro;
|
||||
params.shade_rw = shade_target_rw;
|
||||
params.albedo_ro = albedo_target_ro;
|
||||
|
||||
params.screen_dims = frame->screen_dims;
|
||||
params.albedo_ro = albedo_target_ro;
|
||||
|
||||
params.tiles = gpu_tiles_ref;
|
||||
params.quads = quads_ref;
|
||||
@ -4463,12 +4463,9 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
V_QuadVS, V_QuadPS,
|
||||
G_CountBuffer(quads_buff, V_Quad), G_QuadIndices(),
|
||||
1, &G_Rt(albedo_target, G_BlendMode_CompositeStraightAlpha),
|
||||
shade_viewport, shade_scissor,
|
||||
screen_viewport, screen_scissor,
|
||||
G_RasterMode_TriangleList
|
||||
);
|
||||
|
||||
// Transition albedo to readonly
|
||||
G_DumbMemoryLayoutSync(frame->cl, albedo_target, G_Layout_DirectQueue_ShaderRead);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
@ -4488,6 +4485,14 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
G_DumbGlobalMemorySync(frame->cl);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- Transition G-buffers
|
||||
|
||||
{
|
||||
// Make albedo readonly
|
||||
G_DumbMemoryLayoutSync(frame->cl, albedo_target, G_Layout_DirectQueue_ShaderRead);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- Shading pass
|
||||
|
||||
|
||||
@ -89,15 +89,14 @@ VertexShader(V_QuadVS, V_QuadPSInput)
|
||||
V_Quad quad = quads[SV_InstanceID];
|
||||
|
||||
Vec2 rect_uv = RectUvFromIdx(SV_VertexID);
|
||||
Vec2 shade_pos = mul(quad.quad_uv_to_shade_af, Vec3(rect_uv, 1));
|
||||
Vec2 screen_pos = mul(quad.quad_uv_to_screen_af, Vec3(rect_uv, 1));
|
||||
|
||||
Vec2 tex_pos_uv = lerp(quad.tex_slice_uv.p0, quad.tex_slice_uv.p1, rect_uv);
|
||||
// Vec2 shade_pos = lerp(quad.p0, quad.p1, rect_uv);
|
||||
Vec2 samp_uv = lerp(quad.tex_slice_uv.p0, quad.tex_slice_uv.p1, rect_uv);
|
||||
|
||||
V_QuadPSInput result;
|
||||
result.sv_position = Vec4(NdcFromPos(shade_pos, params.shade_dims).xy, 0, 1);
|
||||
result.sv_position = Vec4(NdcFromPos(screen_pos, params.screen_dims).xy, 0, 1);
|
||||
result.quad_idx = SV_InstanceID;
|
||||
result.tex_pos_uv = tex_pos_uv;
|
||||
result.samp_uv = samp_uv;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -113,7 +112,7 @@ PixelShader(V_QuadPS, V_QuadPSOutput, V_QuadPSInput input)
|
||||
V_Quad quad = quads[input.quad_idx];
|
||||
|
||||
Texture2D<Vec4> tex = G_Dereference<Vec4>(quad.tex);
|
||||
Vec4 albedo = tex.Sample(clamp_sampler, input.tex_pos_uv);
|
||||
Vec4 albedo = tex.Sample(clamp_sampler, input.samp_uv);
|
||||
|
||||
// Vec4 albedo = Color_Cyan;
|
||||
|
||||
@ -443,38 +442,38 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
}
|
||||
|
||||
// Commit
|
||||
// FIXME: Atomic writes
|
||||
{
|
||||
// FIXME: Atomic write
|
||||
if (is_in_world_bounds)
|
||||
{
|
||||
b32 should_stain = 0;
|
||||
if ((particle.flags & V_ParticleFlag_StainTrail) || ((particle.flags & V_ParticleFlag_StainOnPrune) && particle.exists == 0))
|
||||
{
|
||||
should_stain = 1;
|
||||
}
|
||||
Vec4 color = particle.color;
|
||||
color.a *= old_exists;
|
||||
cells[cell_pos] = color;
|
||||
if (should_stain)
|
||||
{
|
||||
f32 old_dryness = drynesses[cell_pos];
|
||||
Vec4 old_stain = stains[cell_pos];
|
||||
// old_stain = V_DryColor(old_stain, drynesses[cell_pos] * 0.5);
|
||||
// old_stain = V_DryColor(old_stain, old_dryness);
|
||||
Vec4 new_stain = 0;
|
||||
new_stain.rgb = (color.rgb * color.a) + (old_stain.rgb * (1.0 - color.a));
|
||||
new_stain.a = color.a + (old_stain.a * (1.0 - color.a));
|
||||
// new_stain = V_DryColor(new_stain, old_dryness * 0.1);
|
||||
// new_stain = V_DryColor(new_stain, old_dryness * 0.5);
|
||||
b32 should_stain = is_in_world_bounds && (
|
||||
AnyBit(particle.flags, V_ParticleFlag_StainTrail) ||
|
||||
(AnyBit(particle.flags, V_ParticleFlag_StainOnPrune) && particle.exists == 0)
|
||||
);
|
||||
b32 should_draw = is_in_world_bounds;
|
||||
|
||||
stains[cell_pos] = new_stain;
|
||||
drynesses[cell_pos] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
Vec4 color = particle.color;
|
||||
color.a *= old_exists;
|
||||
|
||||
// Stain
|
||||
if (should_stain)
|
||||
{
|
||||
// Prune out of bounds particle
|
||||
particle.exists = 0;
|
||||
f32 old_dryness = drynesses[cell_pos];
|
||||
Vec4 old_stain = stains[cell_pos];
|
||||
// old_stain = V_DryColor(old_stain, drynesses[cell_pos] * 0.5);
|
||||
// old_stain = V_DryColor(old_stain, old_dryness);
|
||||
Vec4 new_stain = 0;
|
||||
new_stain.rgb = (color.rgb * color.a) + (old_stain.rgb * (1.0 - color.a));
|
||||
new_stain.a = color.a + (old_stain.a * (1.0 - color.a));
|
||||
// new_stain = V_DryColor(new_stain, old_dryness * 0.1);
|
||||
// new_stain = V_DryColor(new_stain, old_dryness * 0.5);
|
||||
|
||||
stains[cell_pos] = new_stain;
|
||||
drynesses[cell_pos] = 0;
|
||||
}
|
||||
|
||||
// Draw
|
||||
if (should_draw)
|
||||
{
|
||||
cells[cell_pos] = color;
|
||||
}
|
||||
}
|
||||
particles[particle_idx] = particle;
|
||||
@ -489,7 +488,7 @@ ComputeShader2D(V_ShadeCS, 8, 8)
|
||||
{
|
||||
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
|
||||
RWTexture2D<Vec4> shade_tex = G_Dereference<Vec4>(params.shade_rw);
|
||||
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(params.albedo_ro);
|
||||
// Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(params.albedo_ro);
|
||||
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(params.tiles);
|
||||
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(params.stains);
|
||||
RWTexture2D<f32> drynesses = G_Dereference<f32>(params.drynesses);
|
||||
@ -509,9 +508,89 @@ ComputeShader2D(V_ShadeCS, 8, 8)
|
||||
//- Compute albedo
|
||||
|
||||
Vec4 albedo = 0;
|
||||
|
||||
//////////////////////////////
|
||||
//- Compute result
|
||||
|
||||
Vec4 result = albedo;
|
||||
|
||||
//////////////////////////////
|
||||
//- Write result
|
||||
|
||||
if (all(shade_pos < countof(shade_tex)))
|
||||
{
|
||||
shade_tex[shade_pos] = result;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Composite
|
||||
|
||||
//////////////////////////////
|
||||
//- Vertex shader
|
||||
|
||||
VertexShader(V_CompositeVS, V_CompositePSInput)
|
||||
{
|
||||
Vec2 uv = RectUvFromIdx(SV_VertexID);
|
||||
V_CompositePSInput result;
|
||||
result.sv_position = Vec4(NdcFromUv(uv).xy, 0, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- Pixel shader
|
||||
|
||||
PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
|
||||
{
|
||||
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
|
||||
Texture2D<Vec4> shade_tex = G_Dereference<Vec4>(params.shade_ro);
|
||||
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(params.albedo_ro);
|
||||
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(params.stains);
|
||||
RWTexture2D<Vec4> cells = G_Dereference<Vec4>(params.cells);
|
||||
RWTexture2D<f32> drynesses = G_Dereference<f32>(params.drynesses);
|
||||
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(params.tiles);
|
||||
SamplerState clamp_sampler = G_Dereference(params.pt_clamp_sampler);
|
||||
|
||||
Vec2 screen_pos = input.sv_position.xy;
|
||||
Vec2 world_pos = mul(params.af.screen_to_world, Vec3(screen_pos, 1));
|
||||
Vec2 tile_pos = mul(params.af.world_to_tile, Vec3(world_pos, 1));
|
||||
Vec2 cell_pos = floor(mul(params.af.world_to_cell, Vec3(world_pos, 1)));
|
||||
Vec2 shade_pos = mul(params.af.screen_to_shade, Vec3(screen_pos.xy, 1));
|
||||
|
||||
f32 half_thickness = 1;
|
||||
Vec2 half_world_dims = Vec2(P_WorldPitch, P_WorldPitch) * 0.5;
|
||||
Vec2 world_bounds_screen_p0 = mul(params.af.world_to_screen, Vec3(-half_world_dims.xy, 1));
|
||||
Vec2 world_bounds_screen_p1 = mul(params.af.world_to_screen, Vec3(half_world_dims.xy, 1));
|
||||
b32 is_in_world_bounds = (
|
||||
screen_pos.x > (world_bounds_screen_p0.x - half_thickness) &&
|
||||
screen_pos.y > (world_bounds_screen_p0.y - half_thickness) &&
|
||||
screen_pos.x < (world_bounds_screen_p1.x + half_thickness) &&
|
||||
screen_pos.y < (world_bounds_screen_p1.y + half_thickness)
|
||||
);
|
||||
|
||||
P_TileKind tile = tiles.Load(Vec3(tile_pos, 0));
|
||||
P_TileKind equipped_tile = params.equipped_tile;
|
||||
|
||||
//////////////////////////////
|
||||
//- Shade color
|
||||
|
||||
// Vec4 shade_color = 0;
|
||||
// if (all(shade_pos >= Vec2(0, 0)) && all(shade_pos < countof(shade_tex)))
|
||||
// {
|
||||
// Vec2 shade_uv = shade_pos / countof(shade_tex);
|
||||
// shade_color = shade_tex.SampleLevel(clamp_sampler, shade_uv, 0);
|
||||
// }
|
||||
|
||||
//////////////////////////////
|
||||
//- Albedo color
|
||||
|
||||
Vec4 albedo_color = 0;
|
||||
{
|
||||
//////////////////////////////
|
||||
//- Tile color
|
||||
|
||||
// TODO: Remove this
|
||||
|
||||
b32 tile_is_wall = 0;
|
||||
Vec4 tile_color = Vec4(0.025, 0.025, 0.025, 1);
|
||||
if (is_in_world_bounds)
|
||||
@ -581,10 +660,9 @@ ComputeShader2D(V_ShadeCS, 8, 8)
|
||||
}
|
||||
}
|
||||
|
||||
//- Albedo tex color
|
||||
Vec4 albedo_tex_color = albedo_tex.Load(Vec3(shade_pos, 0));
|
||||
|
||||
//////////////////////////////
|
||||
//- Stain color
|
||||
|
||||
Vec4 stain_color = 0;
|
||||
{
|
||||
f32 dryness = drynesses.Load(cell_pos);
|
||||
@ -592,84 +670,38 @@ ComputeShader2D(V_ShadeCS, 8, 8)
|
||||
stain_color.rgb *= 1.0 - (0.75 * tile_is_wall); // Darken wall stains
|
||||
}
|
||||
|
||||
//- Composite albedo
|
||||
albedo = BlendPremul(!tile_is_wall * tile_color, albedo); // Blend floor tile
|
||||
albedo = BlendPremul(!tile_is_wall * stain_color, albedo); // Blend floor stain
|
||||
albedo = BlendPremul(albedo_tex_color, albedo);
|
||||
albedo = BlendPremul(tile_is_wall * tile_color, albedo); // Blend wall tile
|
||||
albedo = BlendPremul(tile_is_wall * stain_color, albedo); // Blend wall stain
|
||||
//////////////////////////////
|
||||
//- Albedo tex
|
||||
|
||||
Vec4 albedo_tex_color = albedo_tex.Load(Vec3(screen_pos, 0));
|
||||
|
||||
//////////////////////////////
|
||||
//- Compose albedo
|
||||
|
||||
albedo_color = BlendPremul(!tile_is_wall * tile_color, albedo_color); // Blend floor tile
|
||||
albedo_color = BlendPremul(!tile_is_wall * stain_color, albedo_color); // Blend floor stain
|
||||
albedo_color = BlendPremul(albedo_tex_color, albedo_color);
|
||||
albedo_color = BlendPremul(tile_is_wall * tile_color, albedo_color); // Blend wall tile
|
||||
albedo_color = BlendPremul(tile_is_wall * stain_color, albedo_color); // Blend wall stain
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- Compute result
|
||||
//- Particle color
|
||||
|
||||
Vec4 result = albedo;
|
||||
// TODO: Remove this
|
||||
|
||||
Vec4 particle_color = 0;
|
||||
if (is_in_world_bounds)
|
||||
{
|
||||
particle_color = cells.Load(cell_pos);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- Write result
|
||||
|
||||
if (all(shade_pos < countof(shade_tex)))
|
||||
{
|
||||
shade_tex[shade_pos] = result;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Composite
|
||||
|
||||
//////////////////////////////
|
||||
//- Vertex shader
|
||||
|
||||
VertexShader(V_CompositeVS, V_CompositePSInput)
|
||||
{
|
||||
Vec2 uv = RectUvFromIdx(SV_VertexID);
|
||||
V_CompositePSInput result;
|
||||
result.sv_position = Vec4(NdcFromUv(uv).xy, 0, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- Pixel shader
|
||||
|
||||
PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
|
||||
{
|
||||
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
|
||||
Texture2D<Vec4> shade_tex = G_Dereference<Vec4>(params.shade_ro);
|
||||
SamplerState clamp_sampler = G_Dereference(params.pt_clamp_sampler);
|
||||
|
||||
Vec2 screen_pos = input.sv_position.xy;
|
||||
|
||||
Vec2 world_pos = mul(params.af.screen_to_world, Vec3(screen_pos, 1));
|
||||
Vec2 tile_pos = mul(params.af.world_to_tile, Vec3(world_pos, 1));
|
||||
P_TileKind equipped_tile = params.equipped_tile;
|
||||
|
||||
f32 half_thickness = 1;
|
||||
|
||||
Vec2 half_world_dims = Vec2(P_WorldPitch, P_WorldPitch) * 0.5;
|
||||
Vec2 world_bounds_screen_p0 = mul(params.af.world_to_screen, Vec3(-half_world_dims.xy, 1));
|
||||
Vec2 world_bounds_screen_p1 = mul(params.af.world_to_screen, Vec3(half_world_dims.xy, 1));
|
||||
b32 is_in_world_bounds = (
|
||||
screen_pos.x > (world_bounds_screen_p0.x - half_thickness) &&
|
||||
screen_pos.y > (world_bounds_screen_p0.y - half_thickness) &&
|
||||
screen_pos.x < (world_bounds_screen_p1.x + half_thickness) &&
|
||||
screen_pos.y < (world_bounds_screen_p1.y + half_thickness)
|
||||
);
|
||||
|
||||
Vec2 shade_pos = mul(params.af.screen_to_shade, Vec3(screen_pos.xy, 1));
|
||||
|
||||
//- Shaded color
|
||||
Vec4 shade_color = 0;
|
||||
if (all(shade_pos >= Vec2(0, 0)) && all(shade_pos < countof(shade_tex)))
|
||||
{
|
||||
Vec2 shade_uv = shade_pos / countof(shade_tex);
|
||||
shade_color = shade_tex.SampleLevel(clamp_sampler, shade_uv, 0);
|
||||
}
|
||||
|
||||
//- Tile selection overlay
|
||||
|
||||
Vec4 selection_color = 0;
|
||||
if (params.has_mouse_focus && params.selection_mode == V_SelectionMode_Tile)
|
||||
{
|
||||
|
||||
Vec4 border_color = LinearFromSrgb(Vec4(1, 1, 1, 1));
|
||||
// Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.4, 0.4, 0.25));
|
||||
Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.8, 0.4, 0.6));
|
||||
@ -713,7 +745,9 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
|
||||
selection_color.rgb *= selection_color.a;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- Grid overlay
|
||||
|
||||
Vec4 overlay_color = 0;
|
||||
if (is_in_world_bounds)
|
||||
{
|
||||
@ -771,9 +805,13 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
|
||||
overlay_color.rgb *= overlay_color.a;
|
||||
}
|
||||
|
||||
//- Composite
|
||||
//////////////////////////////
|
||||
//- Blend
|
||||
|
||||
Vec4 result = Vec4(0, 0, 0, 1);
|
||||
result = BlendPremul(shade_color, result);
|
||||
// result = BlendPremul(shade_color, result);
|
||||
result = BlendPremul(albedo_color, result);
|
||||
result = BlendPremul(particle_color, result);
|
||||
result = BlendPremul(selection_color, result);
|
||||
result = BlendPremul(overlay_color, result);
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ Struct(V_QuadPSInput)
|
||||
{
|
||||
Semantic(Vec4, sv_position);
|
||||
Semantic(nointerpolation u32, quad_idx);
|
||||
Semantic(Vec2, tex_pos_uv);
|
||||
Semantic(Vec2, samp_uv);
|
||||
};
|
||||
|
||||
Struct(V_QuadPSOutput)
|
||||
|
||||
@ -183,7 +183,7 @@ Enum(V_QuadFlag)
|
||||
Struct(V_Quad)
|
||||
{
|
||||
V_QuadFlag flags;
|
||||
Affine quad_uv_to_shade_af;
|
||||
Affine quad_uv_to_screen_af;
|
||||
G_Texture2DRef tex;
|
||||
Rng2 tex_slice_uv;
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user