1
0
mirror of https://github.com/FunkyFr3sh/cnc-ddraw.git synced 2025-03-15 06:04:49 +01:00

preliminary libretro GLSL shader support https://github.com/libretro/glsl-shaders

This commit is contained in:
FunkyFr3sh 2018-05-12 12:28:07 +02:00
parent 0e511f1a7d
commit 87450e320f
6 changed files with 284 additions and 34 deletions

View File

@ -90,6 +90,7 @@ typedef struct IDirectDrawImpl
BOOL maintas;
BOOL fakecursorpos;
BOOL noactivateapp;
char shader[MAX_PATH];
} IDirectDrawImpl;

View File

@ -5,7 +5,8 @@
void OpenGL_Init();
BOOL OpenGL_ExtExists(char *ext);
GLuint OpenGL_BuildProgram(const GLchar **vertSource, const GLchar **fragSource);
GLuint OpenGL_BuildProgram(const GLchar *vertSource, const GLchar *fragSource);
GLuint OpenGL_BuildProgramFromFile(const char *filePath);
// Program
extern PFNGLCREATEPROGRAMPROC glCreateProgram;
@ -27,6 +28,7 @@ extern PFNGLUNIFORM1FVPROC glUniform1fv;
extern PFNGLUNIFORM2FVPROC glUniform2fv;
extern PFNGLUNIFORM3FVPROC glUniform3fv;
extern PFNGLUNIFORM4FVPROC glUniform4fv;
extern PFNGLUNIFORM4FPROC glUniform4f;
extern PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
extern PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
extern PFNGLVERTEXATTRIB1FPROC glVertexAttrib1f;
@ -51,6 +53,7 @@ extern PFNGLGENBUFFERSPROC glGenBuffers;
extern PFNGLBINDBUFFERPROC glBindBuffer;
extern PFNGLBUFFERDATAPROC glBufferData;
extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
extern PFNGLDELETEBUFFERSPROC glDeleteBuffers;
extern PFNGLGENBUFFERSARBPROC glGenBuffersARB;
extern PFNGLBINDBUFFERARBPROC glBindBufferARB;
@ -62,3 +65,10 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLACTIVETEXTUREARBPROC glActiveTexture;
extern PFNGLCLIENTACTIVETEXTUREPROC glClientActiveTexture;
extern PFNGLMULTITEXCOORD2FPROC glMultiTexCoord2f;
extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
extern PFNGLDRAWBUFFERSPROC glDrawBuffers;
extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;

View File

@ -978,7 +978,7 @@ HRESULT WINAPI DirectDrawCreate(GUID FAR* lpGUID, LPDIRECTDRAW FAR* lplpDD, IUnk
"adjmouse=false\n"
"; enable C&C video resize hack, auto = auto-detect game, true = forced, false = disabled\n"
"vhack=false\n"
"; switch between OpenGL (opengl) and software (gdi) renderers, latter supports less features but might be faster depending on the GPU\n"
"; switch between OpenGL (opengl) and software (gdi) renderers\n"
"renderer=gdi\n"
"; force CPU0 affinity, avoids crashes with RA, *might* have a performance impact\n"
"singlecpu=true\n"
@ -1146,6 +1146,9 @@ HRESULT WINAPI DirectDrawCreate(GUID FAR* lpGUID, LPDIRECTDRAW FAR* lplpDD, IUnk
This->renderer = render_main;
}
// to do: read .glslp config file instead of the shader and apply the correct settings
GetPrivateProfileStringA("ddraw", "shader", "", This->shader, sizeof(This->shader), SettingsIniPath);
GetPrivateProfileStringA("ddraw", "singlecpu", "true", tmp, sizeof(tmp), SettingsIniPath);
if (tolower(tmp[0]) == 'y' || tolower(tmp[0]) == 't' || tolower(tmp[0]) == 'e' || tmp[0] == '1')
{

View File

@ -23,6 +23,7 @@ PFNGLUNIFORM1FVPROC glUniform1fv = NULL;
PFNGLUNIFORM2FVPROC glUniform2fv = NULL;
PFNGLUNIFORM3FVPROC glUniform3fv = NULL;
PFNGLUNIFORM4FVPROC glUniform4fv = NULL;
PFNGLUNIFORM4FPROC glUniform4f = NULL;
PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv = NULL;
PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation = NULL;
PFNGLVERTEXATTRIB1FPROC glVertexAttrib1f = NULL;
@ -47,6 +48,7 @@ PFNGLGENBUFFERSPROC glGenBuffers = NULL;
PFNGLBINDBUFFERPROC glBindBuffer = NULL;
PFNGLBUFFERDATAPROC glBufferData = NULL;
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = NULL;
PFNGLDELETEBUFFERSPROC glDeleteBuffers = NULL;
PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;
PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;
@ -59,6 +61,13 @@ PFNGLACTIVETEXTUREARBPROC glActiveTexture = NULL;
PFNGLCLIENTACTIVETEXTUREPROC glClientActiveTexture = NULL;
PFNGLMULTITEXCOORD2FPROC glMultiTexCoord2f = NULL;
PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers = NULL;
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = NULL;
PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = NULL;
PFNGLDRAWBUFFERSPROC glDrawBuffers = NULL;
PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus = NULL;
PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers = NULL;
void OpenGL_Init()
{
// Program
@ -81,6 +90,7 @@ void OpenGL_Init()
glUniform2fv = (PFNGLUNIFORM2FVPROC)wglGetProcAddress("glUniform2fv");
glUniform3fv = (PFNGLUNIFORM3FVPROC)wglGetProcAddress("glUniform3fv");
glUniform4fv = (PFNGLUNIFORM4FVPROC)wglGetProcAddress("glUniform4fv");
glUniform4f = (PFNGLUNIFORM4FPROC)wglGetProcAddress("glUniform4f");
glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)wglGetProcAddress("glUniformMatrix4fv");
glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)wglGetProcAddress("glGetAttribLocation");
glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)wglGetProcAddress("glVertexAttrib1f");
@ -103,6 +113,7 @@ void OpenGL_Init()
glBindBuffer = (PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer");
glBufferData = (PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData");
glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)wglGetProcAddress("glVertexAttribPointer");
glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)wglGetProcAddress("glDeleteBuffers");
glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB");
glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB");
@ -114,6 +125,13 @@ void OpenGL_Init()
glActiveTexture = (PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTexture");
glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC)wglGetProcAddress("glClientActiveTexture");
glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC)wglGetProcAddress("glMultiTexCoord2f");
glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress("glGenFramebuffers");
glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebuffer");
glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)wglGetProcAddress("glFramebufferTexture2D");
glDrawBuffers = (PFNGLDRAWBUFFERSPROC)wglGetProcAddress("glDrawBuffers");
glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress("glCheckFramebufferStatus");
glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)wglGetProcAddress("glDeleteFramebuffers");
}
BOOL OpenGL_ExtExists(char *ext)
@ -127,7 +145,7 @@ BOOL OpenGL_ExtExists(char *ext)
return FALSE;
}
GLuint OpenGL_BuildProgram(const GLchar **vertSource, const GLchar **fragSource)
GLuint OpenGL_BuildProgram(const GLchar *vertSource, const GLchar *fragSource)
{
if (!glCreateShader || !glShaderSource || !glCompileShader || !glCreateProgram ||
!glAttachShader || !glLinkProgram || !glUseProgram || !glDetachShader)
@ -139,8 +157,11 @@ GLuint OpenGL_BuildProgram(const GLchar **vertSource, const GLchar **fragSource)
if (!vertShader || !fragShader)
return 0;
glShaderSource(vertShader, 1, vertSource, NULL);
glShaderSource(fragShader, 1, fragSource, NULL);
const GLchar *vertSrc[2] = { "#define VERTEX\n", vertSource };
const GLchar *fragSrc[2] = { "#define FRAGMENT\n", fragSource };
glShaderSource(vertShader, 2, vertSrc, NULL);
glShaderSource(fragShader, 2, fragSrc, NULL);
GLint isCompiled = 0;
@ -199,3 +220,30 @@ GLuint OpenGL_BuildProgram(const GLchar **vertSource, const GLchar **fragSource)
return program;
}
GLuint OpenGL_BuildProgramFromFile(const char *filePath)
{
GLuint program = 0;
FILE *file = fopen(filePath, "rb");
if (file)
{
fseek(file, 0, SEEK_END);
long fileSize = ftell(file);
fseek(file, 0, SEEK_SET);
char *source = malloc(fileSize + 1);
if (source)
{
fread(source, fileSize, 1, file);
fclose(file);
source[fileSize] = 0;
program = OpenGL_BuildProgram(source, source);
free(source);
}
}
return program;
}

View File

@ -21,7 +21,7 @@
#include "main.h"
#include "surface.h"
const GLchar *PaletteVertShaderSrc =
const GLchar *PassthroughVertShaderSrc =
"//Vertex shader\n"
"#version 110\n"
"varying vec2 TexCoord0; \n"
@ -80,6 +80,9 @@ DWORD WINAPI render_main(void)
if (ddraw->render.maxfps == 0)
ddraw->render.maxfps = 125;
if (ddraw->render.maxfps >= 1000)
ddraw->render.maxfps = 0;
if (ddraw->render.maxfps > 0)
frame_len = 1000.0f / ddraw->render.maxfps;
@ -90,7 +93,14 @@ DWORD WINAPI render_main(void)
GLuint paletteConvProgram = 0;
if (glGetUniformLocation && glActiveTexture && glUniform1i)
paletteConvProgram = OpenGL_BuildProgram(&PaletteVertShaderSrc, &PaletteFragShaderSrc);
paletteConvProgram = OpenGL_BuildProgram(PassthroughVertShaderSrc, PaletteFragShaderSrc);
GLuint scaleProgram = 0;
if (glGenFramebuffers && glBindFramebuffer && glFramebufferTexture2D && glDrawBuffers &&
glCheckFramebufferStatus && glUniform4f && glActiveTexture && glUniform1i &&
glGetAttribLocation && glGenBuffers && glBindBuffer && glBufferData && glVertexAttribPointer &&
glEnableVertexAttribArray && glUniform2fv && glUniformMatrix4fv)
scaleProgram = OpenGL_BuildProgramFromFile(ddraw->shader);
// primary surface texture
GLuint surfaceTexId = 0;
@ -125,22 +135,122 @@ DWORD WINAPI render_main(void)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
while (glGetError() != GL_NO_ERROR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
if (glGetError() != GL_NO_ERROR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glViewport(
ddraw->render.viewport.x, ddraw->render.viewport.y,
ddraw->render.viewport.width, ddraw->render.viewport.height);
glBindTexture(GL_TEXTURE_2D, 0);
GLint surfaceUniLoc = 0, paletteUniLoc = 0;
if (paletteConvProgram)
{
glUseProgram(paletteConvProgram);
surfaceUniLoc = glGetUniformLocation(paletteConvProgram, "SurfaceTex");
paletteUniLoc = glGetUniformLocation(paletteConvProgram, "PaletteTex");
}
GLint textureUniLoc = -1, texCoordUniLoc = -1, frameCountUniLoc = -1;
GLuint frameBufferId = 0;
GLuint frameBufferTexId = 0;
GLuint vboBuffers[3];
if (scaleProgram)
{
glUseProgram(scaleProgram);
GLint vertexCoordUniLoc = glGetAttribLocation(scaleProgram, "VertexCoord");
texCoordUniLoc = glGetAttribLocation(scaleProgram, "TexCoord");
textureUniLoc = glGetUniformLocation(scaleProgram, "Texture");
frameCountUniLoc = glGetUniformLocation(scaleProgram, "FrameCount");
glGenBuffers(3, vboBuffers);
glBindBuffer(GL_ARRAY_BUFFER, vboBuffers[0]);
static const GLfloat vertexCoord[] = {
-1.0f, 1.0f,
1.0f, 1.0f,
1.0f,-1.0f,
-1.0f,-1.0f,
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoord), vertexCoord, GL_STATIC_DRAW);
glVertexAttribPointer(vertexCoordUniLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(vertexCoordUniLoc);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboBuffers[2]);
static const GLushort indices[] =
{
0, 1, 2,
0, 2, 3,
};
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
float inputSize[2], outputSize[2], textureSize[2];
inputSize[0] = ddraw->width;
inputSize[1] = ddraw->height;
textureSize[0] = tex_width;
textureSize[1] = tex_height;
outputSize[0] = ddraw->render.viewport.width;
outputSize[1] = ddraw->render.viewport.height;
glUniform2fv(glGetUniformLocation(scaleProgram, "OutputSize"), 1, outputSize);
glUniform2fv(glGetUniformLocation(scaleProgram, "TextureSize"), 1, textureSize);
glUniform2fv(glGetUniformLocation(scaleProgram, "InputSize"), 1, inputSize);
glUniform4f(glGetAttribLocation(scaleProgram, "Color"), 1, 1, 1, 1);
glUniform1i(glGetUniformLocation(scaleProgram, "FrameDirection"), 1);
const float mvpMatrix[16] = {
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1,
};
glUniformMatrix4fv(glGetUniformLocation(scaleProgram, "MVPMatrix"), 1, GL_FALSE, mvpMatrix);
glGenFramebuffers(1, &frameBufferId);
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferId);
glGenTextures(1, &frameBufferTexId);
glBindTexture(GL_TEXTURE_2D, frameBufferTexId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, tex_width, tex_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, frameBufferTexId, 0);
GLenum drawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, drawBuffers);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
glDeleteTextures(1, &frameBufferTexId);
if (glDeleteFramebuffers)
glDeleteFramebuffers(1, &frameBufferId);
if (glDeleteProgram)
glDeleteProgram(scaleProgram);
scaleProgram = 0;
if (glDeleteBuffers)
glDeleteBuffers(3, vboBuffers);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
glBindTexture(GL_TEXTURE_2D, 0);
glEnable(GL_TEXTURE_2D);
while (ddraw->render.run && WaitForSingleObject(ddraw->render.sem, INFINITE) != WAIT_FAILED)
@ -164,19 +274,6 @@ DWORD WINAPI render_main(void)
if (ddraw->render.maxfps > 0)
tick_start = timeGetTime();
if (paletteConvProgram)
{
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, paletteTexId);
glUniform1i(paletteUniLoc, 0);
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, surfaceTexId);
glUniform1i(surfaceUniLoc, 1);
}
EnterCriticalSection(&ddraw->cs);
if (ddraw->primary && ddraw->primary->palette)
@ -230,12 +327,90 @@ DWORD WINAPI render_main(void)
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, ddraw->width, ddraw->height, GL_RGBA, GL_UNSIGNED_BYTE, tex);
}
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0, 0); glVertex2f(-1, 1);
glTexCoord2f(scale_w, 0); glVertex2f(1, 1);
glTexCoord2f(scale_w, scale_h); glVertex2f(1, -1);
glTexCoord2f(0, scale_h); glVertex2f(-1, -1);
glEnd();
if (paletteConvProgram)
{
glUseProgram(paletteConvProgram);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, paletteTexId);
glUniform1i(paletteUniLoc, 0);
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, surfaceTexId);
glUniform1i(surfaceUniLoc, 1);
glActiveTexture(GL_TEXTURE0);
}
if (scaleProgram)
{
// draw surface into framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferId);
glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0, 0, tex_width, tex_height);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0, 0); glVertex2f(-1, -1);
glTexCoord2f(0, 1); glVertex2f(-1, 1);
glTexCoord2f(1, 1); glVertex2f(1, 1);
glTexCoord2f(1, 0); glVertex2f(1, -1);
glEnd();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glPopAttrib();
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
// apply filter
glBindBuffer(GL_ARRAY_BUFFER, vboBuffers[1]);
GLfloat texCoord[] = {
0.0f, 0.0f,
scale_w, 0.0f,
scale_w, scale_h,
0, scale_h,
};
glBufferData(GL_ARRAY_BUFFER, sizeof(texCoord), texCoord, GL_STATIC_DRAW);
glVertexAttribPointer(texCoordUniLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(texCoordUniLoc);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboBuffers[2]);
glUseProgram(scaleProgram);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, frameBufferTexId);
glUniform1i(textureUniLoc, 0);
static int frames = 1;
if (frameCountUniLoc != -1)
glUniform1i(frameCountUniLoc, frames++);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
else
{
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0, 0); glVertex2f(-1, 1);
glTexCoord2f(scale_w, 0); glVertex2f(1, 1);
glTexCoord2f(scale_w, scale_h); glVertex2f(1, -1);
glTexCoord2f(0, scale_h); glVertex2f(-1, -1);
glEnd();
}
if (scaleProgram && !paletteConvProgram)
glUseProgram(0);
glBindTexture(GL_TEXTURE_2D, 0);
@ -253,14 +428,28 @@ DWORD WINAPI render_main(void)
HeapFree(GetProcessHeap(), 0, tex);
glDeleteTextures(1, &surfaceTexId);
glDeleteTextures(1, &paletteTexId);
if (glUseProgram)
glUseProgram(0);
if (scaleProgram)
{
glDeleteTextures(1, &frameBufferTexId);
if (glDeleteBuffers)
glDeleteBuffers(3, vboBuffers);
if (glDeleteFramebuffers)
glDeleteFramebuffers(1, &frameBufferId);
}
if (glDeleteProgram)
{
if (paletteConvProgram)
glDeleteProgram(paletteConvProgram);
if (scaleProgram)
glDeleteProgram(scaleProgram);
}
wglMakeCurrent(NULL, NULL);

View File

@ -72,14 +72,13 @@ DWORD WINAPI render_soft_main(void)
DWORD frame_len = 0;
if(ddraw->render.maxfps < 0)
{
ddraw->render.maxfps = ddraw->mode.dmDisplayFrequency;
}
if (ddraw->render.maxfps >= 1000)
ddraw->render.maxfps = 0;
if(ddraw->render.maxfps > 0)
{
frame_len = 1000.0f / ddraw->render.maxfps;
}
while (ddraw->render.run && WaitForSingleObject(ddraw->render.sem, INFINITE) != WAIT_FAILED)
{