Merge pull request #12721 from iwubcode/custom_shader_alpha
VideoCommon: allow custom shaders to set the alpha value
This commit is contained in:
commit
16c7869ab2
|
@ -1315,6 +1315,23 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos
|
|||
|
||||
WriteFog(out, uid_data);
|
||||
|
||||
for (std::size_t i = 0; i < custom_details.shaders.size(); i++)
|
||||
{
|
||||
const auto& shader_details = custom_details.shaders[i];
|
||||
|
||||
if (!shader_details.custom_shader.empty())
|
||||
{
|
||||
out.Write("\t{{\n");
|
||||
out.Write("\t\tcustom_data.final_color = float4(prev.r / 255.0, prev.g / 255.0, prev.b "
|
||||
"/ 255.0, prev.a / 255.0);\n");
|
||||
out.Write("\t\tCustomShaderOutput custom_output = {}_{}(custom_data);\n",
|
||||
CUSTOM_PIXELSHADER_COLOR_FUNC, i);
|
||||
out.Write("\t\tprev = int4(custom_output.main_rt.r * 255, custom_output.main_rt.g * 255, "
|
||||
"custom_output.main_rt.b * 255, custom_output.main_rt.a * 255);\n");
|
||||
out.Write("\t}}\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (uid_data->logic_op_enable)
|
||||
WriteLogicOp(out, uid_data);
|
||||
else if (uid_data->emulate_logic_op_with_blend)
|
||||
|
@ -1325,31 +1342,6 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos
|
|||
const bool use_dual_source = !uid_data->no_dual_src || uid_data->blend_enable;
|
||||
WriteColor(out, api_type, uid_data, use_dual_source);
|
||||
|
||||
for (std::size_t i = 0; i < custom_details.shaders.size(); i++)
|
||||
{
|
||||
const auto& shader_details = custom_details.shaders[i];
|
||||
|
||||
if (!shader_details.custom_shader.empty())
|
||||
{
|
||||
out.Write("\t{{\n");
|
||||
if (uid_data->uint_output)
|
||||
{
|
||||
out.Write("\t\tcustom_data.final_color = float4(ocol0.x / 255.0, ocol0.y / 255.0, ocol0.z "
|
||||
"/ 255.0, ocol0.w / 255.0);\n");
|
||||
out.Write("\t\tfloat3 custom_output = {}_{}(custom_data).xyz;\n",
|
||||
CUSTOM_PIXELSHADER_COLOR_FUNC, i);
|
||||
out.Write("\t\tocol0.xyz = uint3(custom_output.x * 255, custom_output.y * 255, "
|
||||
"custom_output.z * 255);\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Write("\t\tcustom_data.final_color = ocol0;\n");
|
||||
out.Write("\t\tocol0.xyz = {}_{}(custom_data).xyz;\n", CUSTOM_PIXELSHADER_COLOR_FUNC, i);
|
||||
}
|
||||
out.Write("\t}}\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (uid_data->blend_enable)
|
||||
WriteBlend(out, uid_data);
|
||||
else if (use_framebuffer_fetch)
|
||||
|
|
|
@ -379,6 +379,11 @@ void WriteCustomShaderStructDef(ShaderCode* out, u32 numtexgens)
|
|||
out->Write("const uint CUSTOM_SHADER_LIGHTING_ATTENUATION_TYPE_SPOT = {}u;\n",
|
||||
static_cast<u32>(AttenuationFunc::Spot));
|
||||
|
||||
out->Write("struct CustomShaderOutput\n");
|
||||
out->Write("{{\n");
|
||||
out->Write("\tfloat4 main_rt;\n");
|
||||
out->Write("}};\n\n");
|
||||
|
||||
out->Write("struct CustomShaderLightData\n");
|
||||
out->Write("{{\n");
|
||||
out->Write("\tfloat3 position;\n");
|
||||
|
|
|
@ -1506,6 +1506,24 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
|||
" }}\n"
|
||||
"\n");
|
||||
|
||||
for (std::size_t i = 0; i < custom_details.shaders.size(); i++)
|
||||
{
|
||||
const auto& shader_details = custom_details.shaders[i];
|
||||
|
||||
if (!shader_details.custom_shader.empty())
|
||||
{
|
||||
out.Write("\t{{\n");
|
||||
out.Write("\t\tcustom_data.final_color = float4(TevResult.r / 255.0, TevResult.g / 255.0, "
|
||||
"TevResult.b / 255.0, TevResult.a / 255.0);\n");
|
||||
out.Write("\t\tCustomShaderOutput custom_output = {}_{}(custom_data);\n",
|
||||
CUSTOM_PIXELSHADER_COLOR_FUNC, i);
|
||||
out.Write(
|
||||
"\t\tTevResult = int4(custom_output.main_rt.r * 255, custom_output.main_rt.g * 255, "
|
||||
"custom_output.main_rt.b * 255, custom_output.main_rt.a * 255);\n");
|
||||
out.Write("\t}}\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (use_framebuffer_fetch)
|
||||
{
|
||||
static constexpr std::array<const char*, 16> logic_op_mode{
|
||||
|
@ -1594,31 +1612,6 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
|||
}
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < custom_details.shaders.size(); i++)
|
||||
{
|
||||
const auto& shader_details = custom_details.shaders[i];
|
||||
|
||||
if (!shader_details.custom_shader.empty())
|
||||
{
|
||||
out.Write("\t{{\n");
|
||||
if (uid_data->uint_output)
|
||||
{
|
||||
out.Write("\t\tcustom_data.final_color = float4(ocol0.x / 255.0, ocol0.y / 255.0, ocol0.z "
|
||||
"/ 255.0, ocol0.w / 255.0);\n");
|
||||
out.Write("\t\tfloat3 custom_output = {}_{}(custom_data).xyz;\n",
|
||||
CUSTOM_PIXELSHADER_COLOR_FUNC, i);
|
||||
out.Write("\t\tocol0.xyz = uint3(custom_output.x * 255, custom_output.y * 255, "
|
||||
"custom_output.z * 255);\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Write("\t\tcustom_data.final_color = ocol0;\n");
|
||||
out.Write("\t\tocol0.xyz = {}_{}(custom_data).xyz;\n", CUSTOM_PIXELSHADER_COLOR_FUNC, i);
|
||||
}
|
||||
out.Write("\t}}\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (bounding_box)
|
||||
{
|
||||
out.Write(" if (bpmem_bounding_box) {{\n"
|
||||
|
|
|
@ -84,22 +84,28 @@ A full example is given below:
|
|||
The shaders are written in GLSL and converted to the target shader that the backend uses internally. The user is expected to provide an entrypoint with the following signature:
|
||||
|
||||
```
|
||||
vec4 custom_main( in CustomShaderData data )
|
||||
CustomShaderOutput custom_main( in CustomShaderData data )
|
||||
```
|
||||
|
||||
`CustomShaderOutput` is used to denote the final output that Dolphin will process and is what is returned by the function. It has the following structure:
|
||||
|
||||
|Name | Type | Since | Description |
|
||||
|-------------------------|-------------------------|-------|-------------------------------------------------------------------------------------------------|
|
||||
|``main_rt`` | vec4 | v1 | The main render target's output color |
|
||||
|
||||
`CustomShaderData` encompasses all the data that Dolphin will pass to the user (in addition to the `samp` variable outlined above which is how textures are accessed). It has the following structure:
|
||||
|
||||
|Name | Type | Since | Description |
|
||||
|-----------------------------|-------------------------|-------|-----------------------------------------------------------------------------------------------|
|
||||
|-----------------------------|-------------------------|-------|----------------------------------------------------------------------------------------------------------------------|
|
||||
|``position`` | vec3 | v1 | The position of this pixel in _view space_ |
|
||||
|``normal`` | vec3 | v1 | The normal of this pixel in _view space_ |
|
||||
|``texcoord`` | vec3[] | v1 | An array of texture coordinates, the amount available is specified by ``texcoord_count`` |
|
||||
|``texcoord_count`` | uint | v1 | The count of texture coordinates |
|
||||
|``texmap_to_texcoord_index`` | uint[] | v1 | An array of texture units to texture coordinate values |
|
||||
|``lights_chan0_color`` | CustomShaderLightData[] | v1 | An array of color lights for channel 0, the amount is specified by ``light_chan0_color_count``|
|
||||
|``lights_chan0_alpha`` | CustomShaderLightData[] | v1 | An array of alpha lights for channel 0, the amount is specified by ``light_chan0_alpha_count``|
|
||||
|``lights_chan1_color`` | CustomShaderLightData[] | v1 | An array of color lights for channel 1, the amount is specified by ``light_chan1_color_count``|
|
||||
|``lights_chan1_alpha`` | CustomShaderLightData[] | v1 | An array of alpha lights for channel 1, the amount is specified by ``light_chan1_alpha_count``|
|
||||
|``lights_chan0_color`` | CustomShaderLightData[] | v1 | An array of color lights for channel 0, the amount is specified by ``light_chan0_color_count`` |
|
||||
|``lights_chan0_alpha`` | CustomShaderLightData[] | v1 | An array of alpha lights for channel 0, the amount is specified by ``light_chan0_alpha_count`` |
|
||||
|``lights_chan1_color`` | CustomShaderLightData[] | v1 | An array of color lights for channel 1, the amount is specified by ``light_chan1_color_count`` |
|
||||
|``lights_chan1_alpha`` | CustomShaderLightData[] | v1 | An array of alpha lights for channel 1, the amount is specified by ``light_chan1_alpha_count`` |
|
||||
|``ambient_lighting`` | vec4[] | v1 | An array of ambient lighting values. Count is two, one for each color channel |
|
||||
|``base_material`` | vec4[] | v1 | An array of the base material values. Count is two, one for each color channel |
|
||||
|``tev_stages`` | CustomShaderTevStage[] | v1 | An array of TEV stages, the amount is specified by ``tev_stage_count`` |
|
||||
|
@ -172,9 +178,11 @@ Below are a handful of examples.
|
|||
The following shader displays the color red on the screen:
|
||||
|
||||
```glsl
|
||||
vec4 custom_main( in CustomShaderData data )
|
||||
CustomShaderOutput custom_main( in CustomShaderData data )
|
||||
{
|
||||
return vec4(1.0, 0.0, 0.0, 1.0);
|
||||
CustomShaderOutput custom_output;
|
||||
custom_output.main_rt = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
return custom_output;
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -183,9 +191,11 @@ vec4 custom_main( in CustomShaderData data )
|
|||
The following shader displays the normal on the screen:
|
||||
|
||||
```glsl
|
||||
vec4 custom_main( in CustomShaderData data )
|
||||
CustomShaderOutput custom_main( in CustomShaderData data )
|
||||
{
|
||||
return vec4(data.normal * 0.5 + 0.5, 1);
|
||||
CustomShaderOutput custom_output;
|
||||
custom_output.main_rt = vec4(data.normal * 0.5 + 0.5, 1);
|
||||
return custom_output;
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -194,9 +204,11 @@ vec4 custom_main( in CustomShaderData data )
|
|||
The following shader displays the contents of the texture denoted in the shader asset as `MY_TEX` with the first texture coordinate data:
|
||||
|
||||
```glsl
|
||||
vec4 custom_main( in CustomShaderData data )
|
||||
CustomShaderOutput custom_main( in CustomShaderData data )
|
||||
{
|
||||
return texture(samp_MY_TEX, TEX_COORD0);
|
||||
CustomShaderOutput custom_output;
|
||||
custom_output.main_rt = texture(samp_MY_TEX, TEX_COORD0);
|
||||
return custom_output;
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -205,7 +217,7 @@ vec4 custom_main( in CustomShaderData data )
|
|||
The following shader would display the contents of the first texture the game uses, ignoring any other operations. If no stages are available or none exist with a texture it would use the final color of all the staging operations:
|
||||
|
||||
```glsl
|
||||
vec4 custom_main( in CustomShaderData data )
|
||||
CustomShaderOutput custom_main( in CustomShaderData data )
|
||||
{
|
||||
vec4 final_color = data.final_color;
|
||||
uint texture_set = 0;
|
||||
|
@ -222,7 +234,9 @@ vec4 custom_main( in CustomShaderData data )
|
|||
}
|
||||
}
|
||||
|
||||
return final_color;
|
||||
CustomShaderOutput custom_output;
|
||||
custom_output.main_rt = final_color;
|
||||
return custom_output;
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -231,7 +245,7 @@ vec4 custom_main( in CustomShaderData data )
|
|||
The following shader would apply the lighting for any point lights used during the draw for channel 0's color lights, using blue as a base color:
|
||||
|
||||
```glsl
|
||||
vec4 custom_main( in CustomShaderData data )
|
||||
CustomShaderOutput custom_main( in CustomShaderData data )
|
||||
{
|
||||
float total_diffuse = 0;
|
||||
for (int i = 0; i < data.light_chan0_color_count; i++)
|
||||
|
@ -246,6 +260,9 @@ vec4 custom_main( in CustomShaderData data )
|
|||
total_diffuse += attn * max(0.0, dot(normal, light_dir));
|
||||
}
|
||||
}
|
||||
return vec4(total_diffuse * vec3(0, 0, 1), 1);
|
||||
|
||||
CustomShaderOutput custom_output;
|
||||
custom_output.main_rt = vec4(total_diffuse * vec3(0, 0, 1), 1);
|
||||
return custom_output;
|
||||
}
|
||||
```
|
Loading…
Reference in New Issue