1 #include <D3Dcompiler.h>
2 #include "GSH_Direct3D9.h"
3 #include "nuanceur/generators/HlslShaderGenerator.h"
4
CreateVertexShader(SHADERCAPS caps)5 CGSH_Direct3D9::VertexShaderPtr CGSH_Direct3D9::CreateVertexShader(SHADERCAPS caps)
6 {
7 HRESULT result = S_OK;
8 auto shaderCode = GenerateVertexShader(caps);
9
10 auto shaderSource = Nuanceur::CHlslShaderGenerator::Generate("main", shaderCode);
11
12 UINT compileFlags = 0;
13 #ifdef _DEBUG
14 compileFlags |= D3DCOMPILE_DEBUG;
15 #endif
16
17 Framework::Win32::CComPtr<ID3DBlob> shaderBinary;
18 Framework::Win32::CComPtr<ID3DBlob> compileErrors;
19 result = D3DCompile(shaderSource.c_str(), shaderSource.length() + 1, "vs", nullptr, nullptr, "main",
20 "vs_3_0", compileFlags, 0, &shaderBinary, &compileErrors);
21 assert(SUCCEEDED(result));
22
23 VertexShaderPtr shader;
24 result = m_device->CreateVertexShader(reinterpret_cast<DWORD*>(shaderBinary->GetBufferPointer()), &shader);
25 assert(SUCCEEDED(result));
26
27 return shader;
28 }
29
CreatePixelShader(SHADERCAPS caps)30 CGSH_Direct3D9::PixelShaderPtr CGSH_Direct3D9::CreatePixelShader(SHADERCAPS caps)
31 {
32 HRESULT result = S_OK;
33 auto shaderCode = GeneratePixelShader(caps);
34
35 auto shaderSource = Nuanceur::CHlslShaderGenerator::Generate("main", shaderCode,
36 Nuanceur::CHlslShaderGenerator::FLAG_COMBINED_SAMPLER_TEXTURE);
37
38 UINT compileFlags = 0;
39 #ifdef _DEBUG
40 compileFlags |= D3DCOMPILE_DEBUG;
41 #endif
42
43 Framework::Win32::CComPtr<ID3DBlob> shaderBinary;
44 Framework::Win32::CComPtr<ID3DBlob> compileErrors;
45 result = D3DCompile(shaderSource.c_str(), shaderSource.length() + 1, "ps", nullptr, nullptr, "main",
46 "ps_3_0", compileFlags, 0, &shaderBinary, &compileErrors);
47 assert(SUCCEEDED(result));
48
49 PixelShaderPtr shader;
50 result = m_device->CreatePixelShader(reinterpret_cast<DWORD*>(shaderBinary->GetBufferPointer()), &shader);
51 assert(SUCCEEDED(result));
52
53 return shader;
54 }
55
GenerateVertexShader(SHADERCAPS caps)56 Nuanceur::CShaderBuilder CGSH_Direct3D9::GenerateVertexShader(SHADERCAPS caps)
57 {
58 using namespace Nuanceur;
59
60 auto b = CShaderBuilder();
61
62 {
63 //Inputs
64 auto inputPosition = CFloat4Lvalue(b.CreateInput(SEMANTIC_POSITION));
65 auto inputTexCoord = CFloat4Lvalue(b.CreateInput(SEMANTIC_TEXCOORD, 0));
66 auto inputColor = CFloat4Lvalue(b.CreateInput(SEMANTIC_TEXCOORD, 1));
67
68 //Outputs
69 auto outputPosition = CFloat4Lvalue(b.CreateOutput(SEMANTIC_SYSTEM_POSITION));
70 auto outputTexCoord = CFloat4Lvalue(b.CreateOutput(SEMANTIC_TEXCOORD, 0));
71 auto outputColor = CFloat4Lvalue(b.CreateOutput(SEMANTIC_TEXCOORD, 1));
72
73 //Constants
74 auto projMatrix = CMatrix44Value(b.CreateUniformMatrix("g_projMatrix"));
75 auto texMatrix = CMatrix44Value(b.CreateUniformMatrix("g_texMatrix"));
76
77 outputPosition = projMatrix * NewFloat4(inputPosition->xyz(), NewFloat(b, 1.0f));
78 outputTexCoord = texMatrix * NewFloat4(inputTexCoord->xyz(), NewFloat(b, 1.0f));
79 outputColor = inputColor->xyzw();
80 }
81
82 return b;
83 }
84
GeneratePixelShader(SHADERCAPS caps)85 Nuanceur::CShaderBuilder CGSH_Direct3D9::GeneratePixelShader(SHADERCAPS caps)
86 {
87 using namespace Nuanceur;
88
89 auto b = CShaderBuilder();
90
91 {
92 //Inputs
93 auto inputTexCoord = CFloat4Lvalue(b.CreateInput(SEMANTIC_TEXCOORD, 0));
94 auto inputColor = CFloat4Lvalue(b.CreateInput(SEMANTIC_TEXCOORD, 1));
95
96 //Outputs
97 auto outputColor = CFloat4Lvalue(b.CreateOutput(SEMANTIC_SYSTEM_COLOR));
98
99 //Textures
100 auto baseTexture = CTexture2DValue(b.CreateTexture2D(0));
101 auto clutTexture = CTexture2DValue(b.CreateTexture2D(1));
102
103 //Temporaries
104 auto texCoord = CFloat2Lvalue(b.CreateTemporary());
105 auto textureColor = CFloat4Lvalue(b.CreateTemporary());
106 auto finalAlpha = CFloatLvalue(b.CreateTemporary());
107
108 texCoord = inputTexCoord->xy() / inputTexCoord->zz();
109 textureColor = NewFloat4(b, 1, 1, 1, 1);
110
111 if(caps.texSourceMode == TEXTURE_SOURCE_MODE_STD)
112 {
113 textureColor = Sample(baseTexture, texCoord);
114 }
115 else if(caps.isIndexedTextureSource())
116 {
117 auto colorIndex = CFloatLvalue(b.CreateTemporary());
118 colorIndex = Sample(baseTexture, texCoord)->x() * NewFloat(b, 255.f);
119 if(caps.texSourceMode == TEXTURE_SOURCE_MODE_IDX4)
120 {
121 colorIndex = colorIndex / NewFloat(b, 15.f);
122 }
123 else if(caps.texSourceMode == TEXTURE_SOURCE_MODE_IDX8)
124 {
125 colorIndex = colorIndex / NewFloat(b, 255.f);
126 }
127 else
128 {
129 assert(false);
130 }
131 textureColor = Sample(clutTexture, NewFloat2(colorIndex, NewFloat(b, 0)));
132 }
133
134 if(caps.texSourceMode != TEXTURE_SOURCE_MODE_NONE)
135 {
136 switch(caps.texFunction)
137 {
138 case TEX0_FUNCTION_MODULATE:
139 textureColor = Clamp(textureColor * inputColor * NewFloat4(b, 2, 2, 2, 2),
140 NewFloat4(b, 0, 0, 0, 0), NewFloat4(b, 1, 1, 1, 1));
141 break;
142 case TEX0_FUNCTION_DECAL:
143 break;
144 default:
145 assert(0);
146 break;
147 }
148 }
149 else
150 {
151 textureColor = inputColor->xyzw();
152 }
153
154 //For proper alpha blending, alpha has to be multiplied by 2 (0x80 -> 1.0)
155 //This has the side effect of not writing a proper value in the framebuffer (should write alpha "as is")
156 finalAlpha = Saturate(textureColor->w() * NewFloat(b, 2));
157 outputColor = NewFloat4(textureColor->xyz(), finalAlpha);
158
159 if(caps.colorOutputWhite)
160 {
161 outputColor = NewFloat4(NewFloat3(b, 1, 1, 1), outputColor->w());
162 }
163 }
164
165 return b;
166 }
167