mirror of https://github.com/snes9xgit/snes9x.git
Use bSNES-style XML-based .shader files for both OpenGL and Direct3D
.shader files are parsed with MSXML. A wrapper-class would be nice, but it does its job.
This commit is contained in:
parent
1c3d31828c
commit
f8fcdcbd72
|
@ -320,6 +320,14 @@ bool CDirect3D::SetShader(const TCHAR *file)
|
||||||
TCHAR folder[MAX_PATH];
|
TCHAR folder[MAX_PATH];
|
||||||
TCHAR rubyLUTfileName[MAX_PATH];
|
TCHAR rubyLUTfileName[MAX_PATH];
|
||||||
TCHAR *slash;
|
TCHAR *slash;
|
||||||
|
char *shaderText = NULL;
|
||||||
|
|
||||||
|
TCHAR errorMsg[MAX_PATH + 50];
|
||||||
|
|
||||||
|
IXMLDOMDocument * pXMLDoc = NULL;
|
||||||
|
IXMLDOMElement * pXDE = NULL;
|
||||||
|
IXMLDOMNode * pXDN = NULL;
|
||||||
|
BSTR queryString, nodeContent;
|
||||||
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
@ -341,6 +349,100 @@ bool CDirect3D::SetShader(const TCHAR *file)
|
||||||
if (file == NULL || *file==TEXT('\0'))
|
if (file == NULL || *file==TEXT('\0'))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
hr = CoCreateInstance(CLSID_DOMDocument,NULL,CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pXMLDoc));
|
||||||
|
|
||||||
|
if(FAILED(hr)) {
|
||||||
|
MessageBox(NULL, TEXT("Error creating XML Parser"), TEXT("Shader Loading Error"),
|
||||||
|
MB_OK|MB_ICONEXCLAMATION);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VARIANT fileName;
|
||||||
|
VARIANT_BOOL ret;
|
||||||
|
fileName.vt = VT_BSTR;
|
||||||
|
#ifdef UNICODE
|
||||||
|
fileName.bstrVal = SysAllocString(file);
|
||||||
|
#else
|
||||||
|
wchar_t tempfilename[MAX_PATH];
|
||||||
|
MultiByteToWideChar(CP_UTF8,0,file,-1,tempfilename,MAX_PATH);
|
||||||
|
fileName.bstrVal = SysAllocString(tempfilename);
|
||||||
|
#endif
|
||||||
|
hr = pXMLDoc->load(fileName,&ret);
|
||||||
|
SysFreeString(fileName.bstrVal);
|
||||||
|
|
||||||
|
if(FAILED(hr) || hr==S_FALSE) {
|
||||||
|
_stprintf(errorMsg,TEXT("Error loading HLSL shader file:\n%s"),file);
|
||||||
|
MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"), MB_OK|MB_ICONEXCLAMATION);
|
||||||
|
pXMLDoc->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VARIANT attributeValue;
|
||||||
|
BSTR attributeName;
|
||||||
|
|
||||||
|
hr = pXMLDoc->get_documentElement(&pXDE);
|
||||||
|
if(FAILED(hr) || hr==S_FALSE) {
|
||||||
|
_stprintf(errorMsg,TEXT("Error loading root element from file:\n%s"),file);
|
||||||
|
MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"), MB_OK|MB_ICONEXCLAMATION);
|
||||||
|
pXMLDoc->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
attributeName=SysAllocString(L"language");
|
||||||
|
pXDE->getAttribute(attributeName,&attributeValue);
|
||||||
|
SysFreeString(attributeName);
|
||||||
|
pXDE->Release();
|
||||||
|
|
||||||
|
if(attributeValue.vt!=VT_BSTR || lstrcmpiW(attributeValue.bstrVal,L"hlsl")) {
|
||||||
|
_stprintf(errorMsg,TEXT("Shader language is <%s>, expected <HLSL> in file:\n%s"),attributeValue.bstrVal,file);
|
||||||
|
MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"), MB_OK|MB_ICONEXCLAMATION);
|
||||||
|
if(attributeValue.vt==VT_BSTR) SysFreeString(attributeValue.bstrVal);
|
||||||
|
pXMLDoc->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(attributeValue.vt==VT_BSTR) SysFreeString(attributeValue.bstrVal);
|
||||||
|
|
||||||
|
queryString=SysAllocString(L"/shader/source");
|
||||||
|
hr = pXMLDoc->selectSingleNode(queryString,&pXDN);
|
||||||
|
SysFreeString(queryString);
|
||||||
|
|
||||||
|
if(hr == S_OK) {
|
||||||
|
hr = pXDN->get_text(&nodeContent);
|
||||||
|
if(hr == S_OK) {
|
||||||
|
int requiredChars = WideCharToMultiByte(CP_ACP,0,nodeContent,-1,shaderText,0,NULL,NULL);
|
||||||
|
shaderText = new char[requiredChars];
|
||||||
|
WideCharToMultiByte(CP_UTF8,0,nodeContent,-1,shaderText,requiredChars,NULL,NULL);
|
||||||
|
}
|
||||||
|
SysFreeString(nodeContent);
|
||||||
|
pXDN->Release();
|
||||||
|
pXDN = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pXMLDoc->Release();
|
||||||
|
|
||||||
|
if(!shaderText) {
|
||||||
|
_stprintf(errorMsg,TEXT("No HLSL shader program in file:\n%s"),file);
|
||||||
|
MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"),
|
||||||
|
MB_OK|MB_ICONEXCLAMATION);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPD3DXBUFFER pBufferErrors = NULL;
|
||||||
|
hr = D3DXCreateEffect( pDevice,shaderText,strlen(shaderText),NULL, NULL,
|
||||||
|
D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY, NULL, &effect,
|
||||||
|
&pBufferErrors );
|
||||||
|
delete[] shaderText;
|
||||||
|
if( FAILED(hr) ) {
|
||||||
|
_stprintf(errorMsg,TEXT("Error parsing HLSL shader file:\n%s"),file);
|
||||||
|
MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"), MB_OK|MB_ICONEXCLAMATION);
|
||||||
|
if(pBufferErrors) {
|
||||||
|
LPVOID pCompilErrors = pBufferErrors->GetBufferPointer();
|
||||||
|
MessageBox(NULL, (const TCHAR*)pCompilErrors, TEXT("FX Compile Error"),
|
||||||
|
MB_OK|MB_ICONEXCLAMATION);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
lstrcpy(folder,file);
|
lstrcpy(folder,file);
|
||||||
slash = _tcsrchr(folder,TEXT('\\'));
|
slash = _tcsrchr(folder,TEXT('\\'));
|
||||||
if(slash)
|
if(slash)
|
||||||
|
@ -357,22 +459,6 @@ bool CDirect3D::SetShader(const TCHAR *file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LPD3DXBUFFER pBufferErrors = NULL;
|
|
||||||
hr = D3DXCreateEffectFromFile( pDevice,file,NULL, NULL,
|
|
||||||
D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY, NULL, &effect,
|
|
||||||
&pBufferErrors );
|
|
||||||
if( FAILED(hr) ) {
|
|
||||||
TCHAR errorMsg[MAX_PATH + 50];
|
|
||||||
_stprintf(errorMsg,TEXT("Error loading HLSL effect file:\n%s"),file);
|
|
||||||
MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"),
|
|
||||||
MB_OK|MB_ICONEXCLAMATION);
|
|
||||||
if(pBufferErrors) {
|
|
||||||
LPVOID pCompilErrors = pBufferErrors->GetBufferPointer();
|
|
||||||
MessageBox(NULL, (const TCHAR*)pCompilErrors, TEXT("FX Compile Error"),
|
|
||||||
MB_OK|MB_ICONEXCLAMATION);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
D3DXHANDLE hTech;
|
D3DXHANDLE hTech;
|
||||||
effect->FindNextValidTechnique(NULL,&hTech);
|
effect->FindNextValidTechnique(NULL,&hTech);
|
||||||
effect->SetTechnique( hTech );
|
effect->SetTechnique( hTech );
|
||||||
|
|
|
@ -257,19 +257,19 @@ void COpenGL::Render(SSurface Src)
|
||||||
if (shaderCompiled) {
|
if (shaderCompiled) {
|
||||||
GLint location;
|
GLint location;
|
||||||
|
|
||||||
float inputSize[2] = { afterRenderWidth, afterRenderHeight };
|
float inputSize[2] = { (float)afterRenderWidth, (float)afterRenderHeight };
|
||||||
location = glGetUniformLocation (shaderProgram, "rubyInputSize");
|
location = glGetUniformLocation (shaderProgram, "rubyInputSize");
|
||||||
glUniform2fv (location, 1, inputSize);
|
glUniform2fv (location, 1, inputSize);
|
||||||
|
|
||||||
RECT windowSize;
|
RECT windowSize;
|
||||||
GetClientRect(hWnd,&windowSize);
|
GetClientRect(hWnd,&windowSize);
|
||||||
|
|
||||||
float outputSize[2] = {GUI.Stretch?windowSize.right:afterRenderWidth,
|
float outputSize[2] = {(float)(GUI.Stretch?windowSize.right:afterRenderWidth),
|
||||||
GUI.Stretch?windowSize.bottom:afterRenderHeight };
|
(float)(GUI.Stretch?windowSize.bottom:afterRenderHeight) };
|
||||||
location = glGetUniformLocation (shaderProgram, "rubyOutputSize");
|
location = glGetUniformLocation (shaderProgram, "rubyOutputSize");
|
||||||
glUniform2fv (location, 1, outputSize);
|
glUniform2fv (location, 1, outputSize);
|
||||||
|
|
||||||
float textureSize[2] = { quadTextureSize, quadTextureSize };
|
float textureSize[2] = { (float)quadTextureSize, (float)quadTextureSize };
|
||||||
location = glGetUniformLocation (shaderProgram, "rubyTextureSize");
|
location = glGetUniformLocation (shaderProgram, "rubyTextureSize");
|
||||||
glUniform2fv (location, 1, textureSize);
|
glUniform2fv (location, 1, textureSize);
|
||||||
}
|
}
|
||||||
|
@ -485,10 +485,13 @@ bool COpenGL::SetShaders(const TCHAR *glslFileName)
|
||||||
{
|
{
|
||||||
char *fragment=NULL, *vertex=NULL;
|
char *fragment=NULL, *vertex=NULL;
|
||||||
IXMLDOMDocument * pXMLDoc = NULL;
|
IXMLDOMDocument * pXMLDoc = NULL;
|
||||||
|
IXMLDOMElement * pXDE = NULL;
|
||||||
IXMLDOMNode * pXDN = NULL;
|
IXMLDOMNode * pXDN = NULL;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
BSTR queryString, nodeContent;
|
BSTR queryString, nodeContent;
|
||||||
|
|
||||||
|
TCHAR errorMsg[MAX_PATH + 50];
|
||||||
|
|
||||||
shaderCompiled = false;
|
shaderCompiled = false;
|
||||||
|
|
||||||
if(fragmentShader) {
|
if(fragmentShader) {
|
||||||
|
@ -538,14 +541,37 @@ bool COpenGL::SetShaders(const TCHAR *glslFileName)
|
||||||
SysFreeString(fileName.bstrVal);
|
SysFreeString(fileName.bstrVal);
|
||||||
|
|
||||||
if(FAILED(hr) || hr==S_FALSE) {
|
if(FAILED(hr) || hr==S_FALSE) {
|
||||||
TCHAR errorMsg[MAX_PATH + 50];
|
|
||||||
_stprintf(errorMsg,TEXT("Error loading GLSL shader file:\n%s"),glslFileName);
|
_stprintf(errorMsg,TEXT("Error loading GLSL shader file:\n%s"),glslFileName);
|
||||||
MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"),
|
MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"), MB_OK|MB_ICONEXCLAMATION);
|
||||||
MB_OK|MB_ICONEXCLAMATION);
|
|
||||||
pXMLDoc->Release();
|
pXMLDoc->Release();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VARIANT attributeValue;
|
||||||
|
BSTR attributeName;
|
||||||
|
|
||||||
|
hr = pXMLDoc->get_documentElement(&pXDE);
|
||||||
|
if(FAILED(hr) || hr==S_FALSE) {
|
||||||
|
_stprintf(errorMsg,TEXT("Error loading root element from file:\n%s"),glslFileName);
|
||||||
|
MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"), MB_OK|MB_ICONEXCLAMATION);
|
||||||
|
pXMLDoc->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
attributeName=SysAllocString(L"language");
|
||||||
|
pXDE->getAttribute(attributeName,&attributeValue);
|
||||||
|
SysFreeString(attributeName);
|
||||||
|
pXDE->Release();
|
||||||
|
|
||||||
|
if(attributeValue.vt!=VT_BSTR || lstrcmpiW(attributeValue.bstrVal,L"glsl")) {
|
||||||
|
_stprintf(errorMsg,TEXT("Shader language is <%s>, expected <GLSL> in file:\n%s"),attributeValue.bstrVal,glslFileName);
|
||||||
|
MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"), MB_OK|MB_ICONEXCLAMATION);
|
||||||
|
if(attributeValue.vt==VT_BSTR) SysFreeString(attributeValue.bstrVal);
|
||||||
|
pXMLDoc->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(attributeValue.vt==VT_BSTR) SysFreeString(attributeValue.bstrVal);
|
||||||
|
|
||||||
queryString=SysAllocString(L"/shader/fragment");
|
queryString=SysAllocString(L"/shader/fragment");
|
||||||
hr = pXMLDoc->selectSingleNode(queryString,&pXDN);
|
hr = pXMLDoc->selectSingleNode(queryString,&pXDN);
|
||||||
SysFreeString(queryString);
|
SysFreeString(queryString);
|
||||||
|
@ -581,10 +607,8 @@ bool COpenGL::SetShaders(const TCHAR *glslFileName)
|
||||||
pXMLDoc->Release();
|
pXMLDoc->Release();
|
||||||
|
|
||||||
if(!fragment && !vertex) {
|
if(!fragment && !vertex) {
|
||||||
TCHAR errorMsg[MAX_PATH + 50];
|
|
||||||
_stprintf(errorMsg,TEXT("No vertex or fragment program in file:\n%s"),glslFileName);
|
_stprintf(errorMsg,TEXT("No vertex or fragment program in file:\n%s"),glslFileName);
|
||||||
MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"),
|
MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"), MB_OK|MB_ICONEXCLAMATION);
|
||||||
MB_OK|MB_ICONEXCLAMATION);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue