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