Win32: add support for cg meta shaders (currently opengl only)
This commit is contained in:
parent
3e84a2eaf4
commit
4d2fbc241a
119
win32/CCGShader.cpp
Normal file
119
win32/CCGShader.cpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#include "CCGShader.h"
|
||||||
|
#include "../conffile.h"
|
||||||
|
|
||||||
|
CCGShader::CCGShader(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CCGShader::~CCGShader(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
cgScaleType CCGShader::scaleStringToEnum(const char *scale)
|
||||||
|
{
|
||||||
|
if(!strcasecmp(scale,"source")) {
|
||||||
|
return CG_SCALE_SOURCE;
|
||||||
|
} else if(!strcasecmp(scale,"viewport")) {
|
||||||
|
return CG_SCALE_VIEWPORT;
|
||||||
|
} else if(!strcasecmp(scale,"absolute")) {
|
||||||
|
return CG_SCALE_ABSOLUTE;
|
||||||
|
} else {
|
||||||
|
return CG_SCALE_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCGShader::LoadShader(const char *path)
|
||||||
|
{
|
||||||
|
ConfigFile conf;
|
||||||
|
int shaderCount;
|
||||||
|
char keyName[100];
|
||||||
|
|
||||||
|
shaderPasses.clear();
|
||||||
|
lookupTextures.clear();
|
||||||
|
|
||||||
|
if(strlen(path)<4 || strcasecmp(&path[strlen(path)-4],".cgp")) {
|
||||||
|
shaderPass pass;
|
||||||
|
pass.scaleParams.scaleTypeX = CG_SCALE_NONE;
|
||||||
|
pass.scaleParams.scaleTypeY = CG_SCALE_NONE;
|
||||||
|
pass.linearFilter = false;
|
||||||
|
pass.filterSet = false;
|
||||||
|
strcpy(pass.cgShaderFile,path);
|
||||||
|
shaderPasses.push_back(pass);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
conf.LoadFile(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
shaderCount = conf.GetInt("::shaders",0);
|
||||||
|
|
||||||
|
if(shaderCount<1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for(int i=0;i<shaderCount;i++) {
|
||||||
|
shaderPass pass;
|
||||||
|
sprintf(keyName,"::filter_linear%u",i);
|
||||||
|
pass.linearFilter = conf.GetBool(keyName);
|
||||||
|
pass.filterSet = conf.Exists(keyName);
|
||||||
|
|
||||||
|
sprintf(keyName,"::scale_type%u",i);
|
||||||
|
const char *scaleType = conf.GetString(keyName,"");
|
||||||
|
if(!strcasecmp(scaleType,"")) {
|
||||||
|
sprintf(keyName,"::scale_type_x%u",i);
|
||||||
|
const char *scaleTypeX = conf.GetString(keyName,"");
|
||||||
|
if(*scaleTypeX=='\0' && (i!=(shaderCount-1)))
|
||||||
|
scaleTypeX = "source";
|
||||||
|
pass.scaleParams.scaleTypeX = scaleStringToEnum(scaleTypeX);
|
||||||
|
sprintf(keyName,"::scale_type_y%u",i);
|
||||||
|
const char *scaleTypeY = conf.GetString(keyName,"");
|
||||||
|
if(*scaleTypeY=='\0' && (i!=(shaderCount-1)))
|
||||||
|
scaleTypeY = "source";
|
||||||
|
pass.scaleParams.scaleTypeY = scaleStringToEnum(scaleTypeY);
|
||||||
|
} else {
|
||||||
|
cgScaleType sType = scaleStringToEnum(scaleType);
|
||||||
|
pass.scaleParams.scaleTypeX = sType;
|
||||||
|
pass.scaleParams.scaleTypeY = sType;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(keyName,"::scale%u",i);
|
||||||
|
const char *scaleFloat = conf.GetString(keyName,"");
|
||||||
|
int scaleInt = conf.GetInt(keyName,0);
|
||||||
|
if(!strcasecmp(scaleFloat,"")) {
|
||||||
|
sprintf(keyName,"::scalex%u",i);
|
||||||
|
const char *scaleFloatX = conf.GetString(keyName,"1.0");
|
||||||
|
pass.scaleParams.scaleX = atof(scaleFloatX);
|
||||||
|
pass.scaleParams.absX = conf.GetInt(keyName,1);
|
||||||
|
sprintf(keyName,"::scaley%u",i);
|
||||||
|
const char *scaleFloatY = conf.GetString(keyName,"1.0");
|
||||||
|
pass.scaleParams.scaleY = atof(scaleFloatY);
|
||||||
|
pass.scaleParams.absY = conf.GetInt(keyName,1);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
float floatval = atof(scaleFloat);
|
||||||
|
pass.scaleParams.scaleX = floatval;
|
||||||
|
pass.scaleParams.absX = scaleInt;
|
||||||
|
pass.scaleParams.scaleY = floatval;
|
||||||
|
pass.scaleParams.absY = scaleInt;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(keyName,"::shader%u",i);
|
||||||
|
strcpy(pass.cgShaderFile,conf.GetString(keyName,""));
|
||||||
|
shaderPasses.push_back(pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *shaderIds = conf.GetStringDup("::textures","");
|
||||||
|
|
||||||
|
char *id = strtok(shaderIds,";");
|
||||||
|
while(id!=NULL) {
|
||||||
|
lookupTexture tex;
|
||||||
|
sprintf(keyName,"::%s",id);
|
||||||
|
strcpy(tex.id,id);
|
||||||
|
strcpy(tex.texturePath,conf.GetString(keyName,""));
|
||||||
|
sprintf(keyName,"::%s_linear",id);
|
||||||
|
tex.linearfilter = conf.GetBool(keyName,true);
|
||||||
|
lookupTextures.push_back(tex);
|
||||||
|
id = strtok(NULL,";");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
43
win32/CCGShader.h
Normal file
43
win32/CCGShader.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef CCGSHADER_H
|
||||||
|
#define CCGSHADER_H
|
||||||
|
|
||||||
|
#include "port.h"
|
||||||
|
#include "cgFunctions.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
enum cgScaleType { CG_SCALE_NONE, CG_SCALE_SOURCE, CG_SCALE_VIEWPORT, CG_SCALE_ABSOLUTE };
|
||||||
|
typedef struct _cgScaleParams {
|
||||||
|
cgScaleType scaleTypeX;
|
||||||
|
cgScaleType scaleTypeY;
|
||||||
|
float scaleX;
|
||||||
|
float scaleY;
|
||||||
|
unsigned absX;
|
||||||
|
unsigned absY;
|
||||||
|
} cgScaleParams;
|
||||||
|
|
||||||
|
class CCGShader
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
cgScaleType scaleStringToEnum(const char* scale);
|
||||||
|
public:
|
||||||
|
typedef struct _shaderPass {
|
||||||
|
cgScaleParams scaleParams;
|
||||||
|
bool linearFilter;
|
||||||
|
bool filterSet;
|
||||||
|
char cgShaderFile[PATH_MAX];
|
||||||
|
} shaderPass;
|
||||||
|
typedef struct _lookupTexture {
|
||||||
|
char id[PATH_MAX];
|
||||||
|
char texturePath[PATH_MAX];
|
||||||
|
bool linearfilter;
|
||||||
|
} lookupTexture;
|
||||||
|
|
||||||
|
CCGShader(void);
|
||||||
|
~CCGShader(void);
|
||||||
|
bool LoadShader(const char *path);
|
||||||
|
|
||||||
|
std::vector<shaderPass> shaderPasses;
|
||||||
|
std::vector<lookupTexture> lookupTextures;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
594
win32/CGLCG.cpp
Normal file
594
win32/CGLCG.cpp
Normal file
@ -0,0 +1,594 @@
|
|||||||
|
#include "CGLCG.h"
|
||||||
|
#include "wsnes9x.h"
|
||||||
|
#include "win32_display.h"
|
||||||
|
#include <png.h>
|
||||||
|
|
||||||
|
#ifndef max
|
||||||
|
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float npot(float desired)
|
||||||
|
{
|
||||||
|
float out=512.0;
|
||||||
|
while(out<desired)
|
||||||
|
out*=2;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GLfloat CGLCG::lut_coords[8] = {0, 0, 1, 0, 1, 1, 0, 1};
|
||||||
|
|
||||||
|
CGLCG::CGLCG(CGcontext cgContext)
|
||||||
|
{
|
||||||
|
this->cgContext = cgContext;
|
||||||
|
fboFunctionsLoaded = FALSE;
|
||||||
|
ClearPasses();
|
||||||
|
LoadFBOFunctions();
|
||||||
|
frameCnt=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGLCG::~CGLCG(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGLCG::ClearPasses()
|
||||||
|
{
|
||||||
|
if(shaderPasses.size()>1) {
|
||||||
|
for(std::vector<shaderPass>::iterator it=(shaderPasses.begin()+1);it!=shaderPasses.end();it++) {
|
||||||
|
if(it->cgFragmentProgram)
|
||||||
|
cgDestroyProgram(it->cgFragmentProgram);
|
||||||
|
if(it->cgVertexProgram)
|
||||||
|
cgDestroyProgram(it->cgVertexProgram);
|
||||||
|
if(it->fbo)
|
||||||
|
glDeleteFramebuffers(1,&it->fbo);
|
||||||
|
if(it->tex)
|
||||||
|
glDeleteTextures(1,&it->tex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(std::vector<lookupTexture>::iterator it=lookupTextures.begin();it!=lookupTextures.end();it++) {
|
||||||
|
if(it->tex)
|
||||||
|
glDeleteTextures(1,&it->tex);
|
||||||
|
}
|
||||||
|
shaderPasses.clear();
|
||||||
|
lookupTextures.clear();
|
||||||
|
shaderLoaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGLCG::LoadFBOFunctions()
|
||||||
|
{
|
||||||
|
if(fboFunctionsLoaded)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
const char *extensions = (const char *) glGetString(GL_EXTENSIONS);
|
||||||
|
|
||||||
|
if(extensions && strstr(extensions, "framebuffer_object")) {
|
||||||
|
glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress("glGenFramebuffers");
|
||||||
|
glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)wglGetProcAddress("glDeleteFramebuffers");
|
||||||
|
glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebuffer");
|
||||||
|
glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)wglGetProcAddress("glFramebufferTexture2D");
|
||||||
|
glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress("glCheckFramebufferStatus");
|
||||||
|
glClientActiveTexture = (PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glClientActiveTexture");
|
||||||
|
|
||||||
|
if(glGenFramebuffers && glDeleteFramebuffers && glBindFramebuffer && glFramebufferTexture2D && glClientActiveTexture) {
|
||||||
|
fboFunctionsLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return fboFunctionsLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGLCG::checkForCgError(const char *situation)
|
||||||
|
{
|
||||||
|
char buffer[4096];
|
||||||
|
CGerror error = cgGetError();
|
||||||
|
const char *string = cgGetErrorString(error);
|
||||||
|
|
||||||
|
if (error != CG_NO_ERROR) {
|
||||||
|
sprintf(buffer,
|
||||||
|
"Situation: %s\n"
|
||||||
|
"Error: %s\n\n"
|
||||||
|
"Cg compiler output...\n", situation, string);
|
||||||
|
MessageBoxA(0, buffer,
|
||||||
|
"Cg error", MB_OK|MB_ICONEXCLAMATION);
|
||||||
|
if (error == CG_COMPILER_ERROR) {
|
||||||
|
MessageBoxA(0, cgGetLastListing(cgContext),
|
||||||
|
"Cg compilation error", MB_OK|MB_ICONEXCLAMATION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IS_SLASH(x) ((x) == TEXT('\\') || (x) == TEXT('/'))
|
||||||
|
|
||||||
|
bool CGLCG::LoadShader(const TCHAR *shaderFile)
|
||||||
|
{
|
||||||
|
CCGShader cgShader;
|
||||||
|
TCHAR shaderPath[MAX_PATH];
|
||||||
|
TCHAR tempPath[MAX_PATH];
|
||||||
|
CGprofile vertexProfile, fragmentProfile;
|
||||||
|
GLenum error;
|
||||||
|
|
||||||
|
if(!fboFunctionsLoaded) {
|
||||||
|
MessageBox(NULL, TEXT("Your OpenGL graphics driver does not support framebuffer objects.\nYou will not be able to use CG shaders in OpenGL mode."), TEXT("CG Error"),
|
||||||
|
MB_OK|MB_ICONEXCLAMATION);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
|
||||||
|
fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
|
||||||
|
|
||||||
|
cgGLDisableProfile(vertexProfile);
|
||||||
|
cgGLDisableProfile(fragmentProfile);
|
||||||
|
|
||||||
|
ClearPasses();
|
||||||
|
|
||||||
|
if (shaderFile == NULL || *shaderFile==TEXT('\0'))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
lstrcpy(shaderPath,shaderFile);
|
||||||
|
for(int i=lstrlen(shaderPath); i>=0; i--){
|
||||||
|
if(IS_SLASH(shaderPath[i])){
|
||||||
|
shaderPath[i]=TEXT('\0');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetCurrentDirectory(shaderPath);
|
||||||
|
if(!cgShader.LoadShader(_tToChar(shaderFile)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
cgGLSetOptimalOptions(vertexProfile);
|
||||||
|
cgGLSetOptimalOptions(fragmentProfile);
|
||||||
|
|
||||||
|
shaderPasses.push_back(shaderPass());
|
||||||
|
|
||||||
|
for(std::vector<CCGShader::shaderPass>::iterator it=cgShader.shaderPasses.begin();it!=cgShader.shaderPasses.end();it++) {
|
||||||
|
shaderPasses.push_back(shaderPass());
|
||||||
|
shaderPass &pass = shaderPasses.back();
|
||||||
|
pass.scaleParams = it->scaleParams;
|
||||||
|
pass.linearFilter = (pass.scaleParams.scaleTypeX==CG_SCALE_NONE && !it->filterSet)?GUI.BilinearFilter:it->linearFilter;
|
||||||
|
_tfullpath(tempPath,_tFromChar(it->cgShaderFile),MAX_PATH);
|
||||||
|
char *fileContents = ReadShaderFileContents(tempPath);
|
||||||
|
if(!fileContents)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pass.cgVertexProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents,
|
||||||
|
vertexProfile, "main_vertex", NULL);
|
||||||
|
|
||||||
|
checkForCgError("Compiling vertex program");
|
||||||
|
|
||||||
|
pass.cgFragmentProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents,
|
||||||
|
fragmentProfile, "main_fragment", NULL);
|
||||||
|
|
||||||
|
checkForCgError("Compiling fragment program");
|
||||||
|
|
||||||
|
delete [] fileContents;
|
||||||
|
if(!pass.cgVertexProgram || !pass.cgFragmentProgram) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cgGLLoadProgram(pass.cgVertexProgram);
|
||||||
|
cgGLLoadProgram(pass.cgFragmentProgram);
|
||||||
|
|
||||||
|
glGenFramebuffers(1,&pass.fbo);
|
||||||
|
glGenTextures(1,&pass.tex);
|
||||||
|
glBindTexture(GL_TEXTURE_2D,pass.tex);
|
||||||
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||||
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||||
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(std::vector<CCGShader::lookupTexture>::iterator it=cgShader.lookupTextures.begin();it!=cgShader.lookupTextures.end();it++) {
|
||||||
|
lookupTextures.push_back(lookupTexture());
|
||||||
|
lookupTexture &tex = lookupTextures.back();
|
||||||
|
strcpy(tex.id,it->id);
|
||||||
|
glGenTextures(1,&tex.tex);
|
||||||
|
glBindTexture(GL_TEXTURE_2D,tex.tex);
|
||||||
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||||
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||||
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, it->linearfilter?GL_LINEAR:GL_NEAREST);
|
||||||
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, it->linearfilter?GL_LINEAR:GL_NEAREST);
|
||||||
|
_tfullpath(tempPath,_tFromChar(it->texturePath),MAX_PATH);
|
||||||
|
int strLen = strlen(it->texturePath);
|
||||||
|
if(strLen>4) {
|
||||||
|
if(!strcasecmp(&it->texturePath[strLen-4],".png")) {
|
||||||
|
int width, height;
|
||||||
|
bool hasAlpha;
|
||||||
|
GLubyte *texData;
|
||||||
|
if(loadPngImage(tempPath,width,height,hasAlpha,&texData)) {
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, hasAlpha ? 4 : 3, width,
|
||||||
|
height, 0, hasAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, texData);
|
||||||
|
free(texData);
|
||||||
|
}
|
||||||
|
} else if(!strcasecmp(&it->texturePath[strLen-4],".tga")) {
|
||||||
|
STGA stga;
|
||||||
|
if(loadTGA(tempPath,stga)) {
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, stga.width);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, 4, stga.width,
|
||||||
|
stga.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, stga.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glClientActiveTexture(GL_TEXTURE1);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glTexCoordPointer(2,GL_FLOAT,0,lut_coords);
|
||||||
|
glClientActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
|
shaderLoaded = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGLCG::setTexCoords(int pass,xySize inputSize,xySize textureSize,bool topdown)
|
||||||
|
{
|
||||||
|
float tX = inputSize.x / textureSize.x;
|
||||||
|
float tY = inputSize.y / textureSize.y;
|
||||||
|
|
||||||
|
if(topdown) {
|
||||||
|
shaderPasses[pass].texcoords[0] = 0.0f;
|
||||||
|
shaderPasses[pass].texcoords[1] = tY;
|
||||||
|
shaderPasses[pass].texcoords[2] = tX;
|
||||||
|
shaderPasses[pass].texcoords[3] = tY;
|
||||||
|
shaderPasses[pass].texcoords[4] = tX;
|
||||||
|
shaderPasses[pass].texcoords[5] = 0.0f;
|
||||||
|
shaderPasses[pass].texcoords[6] = 0.0f;
|
||||||
|
shaderPasses[pass].texcoords[7] = 0.0f;
|
||||||
|
} else {
|
||||||
|
shaderPasses[pass].texcoords[0] = 0.0f;
|
||||||
|
shaderPasses[pass].texcoords[1] = 0.0f;
|
||||||
|
shaderPasses[pass].texcoords[2] = tX;
|
||||||
|
shaderPasses[pass].texcoords[3] = 0.0f;
|
||||||
|
shaderPasses[pass].texcoords[4] = tX;
|
||||||
|
shaderPasses[pass].texcoords[5] = tY;
|
||||||
|
shaderPasses[pass].texcoords[6] = 0.0f;
|
||||||
|
shaderPasses[pass].texcoords[7] = tY;
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, 0, shaderPasses[pass].texcoords);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGLCG::Render(GLuint origTex, xySize textureSize, xySize inputSize, xySize viewportSize, xySize windowSize)
|
||||||
|
{
|
||||||
|
GLenum error;
|
||||||
|
frameCnt++;
|
||||||
|
CGprofile vertexProfile, fragmentProfile;
|
||||||
|
|
||||||
|
if(!shaderLoaded)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
|
||||||
|
fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
|
||||||
|
|
||||||
|
cgGLEnableProfile(vertexProfile);
|
||||||
|
cgGLEnableProfile(fragmentProfile);
|
||||||
|
|
||||||
|
shaderPasses[0].tex = origTex;
|
||||||
|
shaderPasses[0].outputSize = inputSize;
|
||||||
|
shaderPasses[0].textureSize = textureSize;
|
||||||
|
|
||||||
|
for(int i=1;i<shaderPasses.size();i++) {
|
||||||
|
switch(shaderPasses[i].scaleParams.scaleTypeX) {
|
||||||
|
case CG_SCALE_ABSOLUTE:
|
||||||
|
shaderPasses[i].outputSize.x = (double)shaderPasses[i].scaleParams.absX;
|
||||||
|
break;
|
||||||
|
case CG_SCALE_SOURCE:
|
||||||
|
shaderPasses[i].outputSize.x = shaderPasses[i-1].outputSize.x * shaderPasses[i].scaleParams.scaleX;
|
||||||
|
break;
|
||||||
|
case CG_SCALE_VIEWPORT:
|
||||||
|
shaderPasses[i].outputSize.x = viewportSize.x * shaderPasses[i].scaleParams.scaleX;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
shaderPasses[i].outputSize.x = viewportSize.x;
|
||||||
|
}
|
||||||
|
switch(shaderPasses[i].scaleParams.scaleTypeY) {
|
||||||
|
case CG_SCALE_ABSOLUTE:
|
||||||
|
shaderPasses[i].outputSize.y = (double)shaderPasses[i].scaleParams.absX;
|
||||||
|
break;
|
||||||
|
case CG_SCALE_SOURCE:
|
||||||
|
shaderPasses[i].outputSize.y = shaderPasses[i-1].outputSize.y * shaderPasses[i].scaleParams.scaleY;
|
||||||
|
break;
|
||||||
|
case CG_SCALE_VIEWPORT:
|
||||||
|
shaderPasses[i].outputSize.y = viewportSize.y * shaderPasses[i].scaleParams.scaleY;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
shaderPasses[i].outputSize.y = viewportSize.y;
|
||||||
|
}
|
||||||
|
float texSize = npot(max(shaderPasses[i].outputSize.x,shaderPasses[i].outputSize.y));
|
||||||
|
shaderPasses[i].textureSize.x = shaderPasses[i].textureSize.y = texSize;
|
||||||
|
setShaderVars(i);
|
||||||
|
setTexCoords(i,shaderPasses[i-1].outputSize,shaderPasses[i-1].textureSize);
|
||||||
|
cgGLBindProgram(shaderPasses[i].cgVertexProgram);
|
||||||
|
cgGLBindProgram(shaderPasses[i].cgFragmentProgram);
|
||||||
|
glBindTexture(GL_TEXTURE_2D,shaderPasses[i].tex);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,(unsigned int)shaderPasses[i].textureSize.x,(unsigned int)shaderPasses[i].textureSize.y,0,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,NULL);
|
||||||
|
glViewport(0,0,shaderPasses[i].outputSize.x,shaderPasses[i].outputSize.y);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER,shaderPasses[i].fbo);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, shaderPasses[i].tex, 0);
|
||||||
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
|
glBindTexture(GL_TEXTURE_2D,shaderPasses[i-1].tex);
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)shaderPasses[i-1].textureSize.x);
|
||||||
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shaderPasses[i].linearFilter?GL_LINEAR:GL_NEAREST);
|
||||||
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, shaderPasses[i].linearFilter?GL_LINEAR:GL_NEAREST);
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
glDrawArrays (GL_QUADS, 0, 4);
|
||||||
|
|
||||||
|
}
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER,0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D,shaderPasses.back().tex);
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)shaderPasses.back().textureSize.x);
|
||||||
|
RECT displayRect=CalculateDisplayRect(shaderPasses.back().outputSize.x,shaderPasses.back().outputSize.y,windowSize.x,windowSize.y);
|
||||||
|
glViewport(displayRect.left,windowSize.y-displayRect.bottom,displayRect.right-displayRect.left,displayRect.bottom-displayRect.top);
|
||||||
|
setTexCoords(shaderPasses.size()-1,shaderPasses.back().outputSize,shaderPasses.back().textureSize,true);
|
||||||
|
|
||||||
|
cgGLDisableProfile(vertexProfile);
|
||||||
|
cgGLDisableProfile(fragmentProfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGLCG::setShaderVars(int pass)
|
||||||
|
{
|
||||||
|
float inputSize[2] = {shaderPasses[pass-1].outputSize.x,shaderPasses[pass-1].outputSize.y};
|
||||||
|
float textureSize[2] = {shaderPasses[pass-1].textureSize.x,shaderPasses[pass-1].textureSize.y};
|
||||||
|
float outputSize[2] = {shaderPasses[pass].outputSize.x,shaderPasses[pass].outputSize.y};
|
||||||
|
|
||||||
|
CGparameter cgpModelViewProj = cgGetNamedParameter(shaderPasses[pass].cgVertexProgram, "modelViewProj");
|
||||||
|
|
||||||
|
cgGLSetStateMatrixParameter(cgpModelViewProj, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);
|
||||||
|
|
||||||
|
#define setProgram2fv(pass,varname,floats)\
|
||||||
|
{\
|
||||||
|
CGparameter cgpf = cgGetNamedParameter(shaderPasses[pass].cgFragmentProgram, varname);\
|
||||||
|
CGparameter cgpv = cgGetNamedParameter(shaderPasses[pass].cgVertexProgram, varname);\
|
||||||
|
if(cgpf)\
|
||||||
|
cgGLSetParameter2fv(cgpf,floats);\
|
||||||
|
if(cgpv)\
|
||||||
|
cgGLSetParameter2fv(cgpv,floats);\
|
||||||
|
}\
|
||||||
|
|
||||||
|
#define setProgram1f(pass,varname,val)\
|
||||||
|
{\
|
||||||
|
CGparameter cgpf = cgGetNamedParameter(shaderPasses[pass].cgFragmentProgram, varname);\
|
||||||
|
CGparameter cgpv = cgGetNamedParameter(shaderPasses[pass].cgVertexProgram, varname);\
|
||||||
|
if(cgpf)\
|
||||||
|
cgGLSetParameter1f(cgpf,val);\
|
||||||
|
if(cgpv)\
|
||||||
|
cgGLSetParameter1f(cgpv,val);\
|
||||||
|
}\
|
||||||
|
|
||||||
|
#define setTextureParameter(pass,varname,val)\
|
||||||
|
{\
|
||||||
|
CGparameter cgpf = cgGetNamedParameter(shaderPasses[pass].cgFragmentProgram, varname);\
|
||||||
|
if(cgpf) {\
|
||||||
|
cgGLSetTextureParameter(cgpf,val);\
|
||||||
|
cgGLEnableTextureParameter(cgpf);\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
|
||||||
|
#define setTexCoordsParameter(pass,varname,val)\
|
||||||
|
{\
|
||||||
|
CGparameter cgpv = cgGetNamedParameter(shaderPasses[pass].cgVertexProgram, varname);\
|
||||||
|
if(cgpv) {\
|
||||||
|
cgGLSetParameterPointer(cgpv, 2, GL_FLOAT, 0, val);\
|
||||||
|
cgGLEnableClientState(cgpv);\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
|
||||||
|
|
||||||
|
setProgram2fv(pass,"IN.video_size",inputSize);
|
||||||
|
setProgram2fv(pass,"IN.texture_size",textureSize);
|
||||||
|
setProgram2fv(pass,"IN.output_size",outputSize);
|
||||||
|
setProgram1f(pass,"IN.frame_count",(float)frameCnt);
|
||||||
|
|
||||||
|
float video_Size[2] = {shaderPasses[0].outputSize.x,shaderPasses[0].outputSize.y};
|
||||||
|
float texture_Size[2] = {shaderPasses[0].textureSize.x,shaderPasses[0].outputSize.y};
|
||||||
|
|
||||||
|
|
||||||
|
setProgram2fv(pass,"ORIG.video_size",video_Size);
|
||||||
|
setProgram2fv(pass,"ORIG.texture_size",texture_Size);
|
||||||
|
setTextureParameter(pass,"ORIG.texture",shaderPasses[0].tex);
|
||||||
|
setTexCoordsParameter(pass,"ORIG.tex_coord",shaderPasses[0].texcoords);
|
||||||
|
|
||||||
|
for(int i=0;i<lookupTextures.size();i++) {
|
||||||
|
setTextureParameter(pass,lookupTextures[i].id,lookupTextures[i].tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pass>1) {
|
||||||
|
for(int i=1;i<pass-1;i++) {
|
||||||
|
char varname[100];
|
||||||
|
float video_Size[2] = {shaderPasses[i].outputSize.x,shaderPasses[i].outputSize.y};
|
||||||
|
float texture_Size[2] = {shaderPasses[i].textureSize.x,shaderPasses[i].outputSize.y};
|
||||||
|
sprintf(varname,"PASS%d.video_size",i);
|
||||||
|
setProgram2fv(i,varname,video_Size);
|
||||||
|
sprintf(varname,"PASS%d.texture_size",i);
|
||||||
|
setProgram2fv(i,varname,texture_Size);
|
||||||
|
sprintf(varname,"PASS%d.texture",i);
|
||||||
|
setTextureParameter(i,varname,shaderPasses[i].tex);
|
||||||
|
sprintf(varname,"PASS%d.tex_coord",i);
|
||||||
|
setTexCoordsParameter(i,varname,shaderPasses[i].texcoords);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGLCG::loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData) {
|
||||||
|
png_structp png_ptr;
|
||||||
|
png_infop info_ptr;
|
||||||
|
unsigned int sig_read = 0;
|
||||||
|
int color_type, interlace_type;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if ((fp = _tfopen(name, TEXT("rb"))) == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Create and initialize the png_struct
|
||||||
|
* with the desired error handler
|
||||||
|
* functions. If you want to use the
|
||||||
|
* default stderr and longjump method,
|
||||||
|
* you can supply NULL for the last
|
||||||
|
* three parameters. We also supply the
|
||||||
|
* the compiler header file version, so
|
||||||
|
* that we know if the application
|
||||||
|
* was compiled with a compatible version
|
||||||
|
* of the library. REQUIRED
|
||||||
|
*/
|
||||||
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
|
||||||
|
if (png_ptr == NULL) {
|
||||||
|
fclose(fp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate/initialize the memory
|
||||||
|
* for image information. REQUIRED. */
|
||||||
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (info_ptr == NULL) {
|
||||||
|
fclose(fp);
|
||||||
|
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set error handling if you are
|
||||||
|
* using the setjmp/longjmp method
|
||||||
|
* (this is the normal method of
|
||||||
|
* doing things with libpng).
|
||||||
|
* REQUIRED unless you set up
|
||||||
|
* your own error handlers in
|
||||||
|
* the png_create_read_struct()
|
||||||
|
* earlier.
|
||||||
|
*/
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||||
|
/* Free all of the memory associated
|
||||||
|
* with the png_ptr and info_ptr */
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
|
||||||
|
fclose(fp);
|
||||||
|
/* If we get here, we had a
|
||||||
|
* problem reading the file */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up the output control if
|
||||||
|
* you are using standard C streams */
|
||||||
|
png_init_io(png_ptr, fp);
|
||||||
|
|
||||||
|
/* If we have already
|
||||||
|
* read some of the signature */
|
||||||
|
png_set_sig_bytes(png_ptr, sig_read);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If you have enough memory to read
|
||||||
|
* in the entire image at once, and
|
||||||
|
* you need to specify only
|
||||||
|
* transforms that can be controlled
|
||||||
|
* with one of the PNG_TRANSFORM_*
|
||||||
|
* bits (this presently excludes
|
||||||
|
* dithering, filling, setting
|
||||||
|
* background, and doing gamma
|
||||||
|
* adjustment), then you can read the
|
||||||
|
* entire image (including pixels)
|
||||||
|
* into the info structure with this
|
||||||
|
* call
|
||||||
|
*
|
||||||
|
* PNG_TRANSFORM_STRIP_16 |
|
||||||
|
* PNG_TRANSFORM_PACKING forces 8 bit
|
||||||
|
* PNG_TRANSFORM_EXPAND forces to
|
||||||
|
* expand a palette into RGB
|
||||||
|
*/
|
||||||
|
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, png_voidp_NULL);
|
||||||
|
|
||||||
|
outWidth = info_ptr->width;
|
||||||
|
outHeight = info_ptr->height;
|
||||||
|
switch (info_ptr->color_type) {
|
||||||
|
case PNG_COLOR_TYPE_RGBA:
|
||||||
|
outHasAlpha = true;
|
||||||
|
break;
|
||||||
|
case PNG_COLOR_TYPE_RGB:
|
||||||
|
outHasAlpha = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
fclose(fp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||||
|
*outData = (unsigned char*) malloc(row_bytes * outHeight);
|
||||||
|
|
||||||
|
png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
for (int i = 0; i < outHeight; i++) {
|
||||||
|
memcpy(*outData+(row_bytes * i), row_pointers[i], row_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean up after the read,
|
||||||
|
* and free any memory allocated */
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
|
||||||
|
|
||||||
|
/* Close the file */
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
/* That's it */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGLCG::loadTGA(const TCHAR *filename, STGA& tgaFile)
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
unsigned char type[4];
|
||||||
|
unsigned char info[6];
|
||||||
|
|
||||||
|
file = _tfopen(filename, TEXT("rb"));
|
||||||
|
|
||||||
|
if (!file)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fread (&type, sizeof (char), 3, file);
|
||||||
|
fseek (file, 12, SEEK_SET);
|
||||||
|
fread (&info, sizeof (char), 6, file);
|
||||||
|
|
||||||
|
//image type either 2 (color) or 3 (greyscale)
|
||||||
|
if (type[1] != 0 || (type[2] != 2 && type[2] != 3))
|
||||||
|
{
|
||||||
|
fclose(file);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tgaFile.width = info[0] + info[1] * 256;
|
||||||
|
tgaFile.height = info[2] + info[3] * 256;
|
||||||
|
tgaFile.byteCount = info[4] / 8;
|
||||||
|
|
||||||
|
if (tgaFile.byteCount != 3 && tgaFile.byteCount != 4) {
|
||||||
|
fclose(file);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
long imageSize = tgaFile.width * tgaFile.height * tgaFile.byteCount;
|
||||||
|
|
||||||
|
//allocate memory for image data
|
||||||
|
unsigned char *tempBuf = new unsigned char[imageSize];
|
||||||
|
tgaFile.data = new unsigned char[tgaFile.width * tgaFile.height * 4];
|
||||||
|
|
||||||
|
//read in image data
|
||||||
|
fread(tempBuf, sizeof(unsigned char), imageSize, file);
|
||||||
|
|
||||||
|
//swap line order and convert to RBGA
|
||||||
|
for(int i=0;i<tgaFile.height;i++) {
|
||||||
|
unsigned char* source = tempBuf + tgaFile.width * (tgaFile.height - 1 - i) * tgaFile.byteCount;
|
||||||
|
unsigned char* destination = tgaFile.data + tgaFile.width * i * 4;
|
||||||
|
for(int j=0;j<tgaFile.width;j++) {
|
||||||
|
destination[0]=source[2];
|
||||||
|
destination[1]=source[1];
|
||||||
|
destination[2]=source[0];
|
||||||
|
destination[3]=tgaFile.byteCount==4?source[3]:0xff;
|
||||||
|
source+=tgaFile.byteCount;
|
||||||
|
destination+=4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete [] tempBuf;
|
||||||
|
tgaFile.byteCount = 4;
|
||||||
|
|
||||||
|
//close file
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
87
win32/CGLCG.h
Normal file
87
win32/CGLCG.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#ifndef CGGLCG_H
|
||||||
|
#define CGGLCG_H
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <gl/gl.h>
|
||||||
|
#include "glext.h"
|
||||||
|
#include "cgFunctions.h"
|
||||||
|
#include "CCGShader.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
typedef struct _xySize {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
} xySize;
|
||||||
|
|
||||||
|
class CGLCG
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef struct _STGA {
|
||||||
|
_STGA() {data = (unsigned char*)0;
|
||||||
|
width = 0;
|
||||||
|
height = 0;
|
||||||
|
byteCount = 0;}
|
||||||
|
|
||||||
|
~_STGA() { delete[] data; data = 0; }
|
||||||
|
|
||||||
|
void destroy() { delete[] data; data = 0; }
|
||||||
|
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
unsigned char byteCount;
|
||||||
|
unsigned char* data;
|
||||||
|
} STGA;
|
||||||
|
typedef struct _shaderPass {
|
||||||
|
cgScaleParams scaleParams;
|
||||||
|
bool linearFilter;
|
||||||
|
CGprogram cgVertexProgram, cgFragmentProgram;
|
||||||
|
GLuint tex;
|
||||||
|
GLuint fbo;
|
||||||
|
xySize outputSize;
|
||||||
|
xySize textureSize;
|
||||||
|
GLfloat texcoords[8];
|
||||||
|
_shaderPass() {cgVertexProgram=NULL;
|
||||||
|
cgFragmentProgram=NULL;
|
||||||
|
fbo=NULL;
|
||||||
|
tex=NULL;}
|
||||||
|
} shaderPass;
|
||||||
|
typedef struct _lookupTexture {
|
||||||
|
char id[PATH_MAX];
|
||||||
|
GLuint tex;
|
||||||
|
_lookupTexture() {tex=NULL;}
|
||||||
|
} lookupTexture;
|
||||||
|
|
||||||
|
std::vector<shaderPass> shaderPasses;
|
||||||
|
std::vector<lookupTexture> lookupTextures;
|
||||||
|
|
||||||
|
bool fboFunctionsLoaded;
|
||||||
|
bool shaderLoaded;
|
||||||
|
bool LoadFBOFunctions();
|
||||||
|
void checkForCgError(const char *situation);
|
||||||
|
void setTexCoords(int pass,xySize inputSize,xySize textureSize,bool topdown=false);
|
||||||
|
void setShaderVars(int pass);
|
||||||
|
bool loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData);
|
||||||
|
bool loadTGA(const TCHAR *filename, STGA& tgaFile);
|
||||||
|
|
||||||
|
CGcontext cgContext;
|
||||||
|
int frameCnt;
|
||||||
|
static const GLfloat lut_coords[8];
|
||||||
|
|
||||||
|
|
||||||
|
PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
|
||||||
|
PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
|
||||||
|
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
|
||||||
|
PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
|
||||||
|
PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
|
||||||
|
PFNGLACTIVETEXTUREPROC glClientActiveTexture;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CGLCG(CGcontext cgContext);
|
||||||
|
~CGLCG(void);
|
||||||
|
|
||||||
|
bool LoadShader(const TCHAR *shaderFile);
|
||||||
|
void Render(GLuint origTex, xySize textureSize, xySize inputSize, xySize viewportSize, xySize windowSize);
|
||||||
|
void ClearPasses();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -211,6 +211,7 @@ COpenGL::COpenGL(void)
|
|||||||
cgVertexProgram = cgFragmentProgram = NULL;
|
cgVertexProgram = cgFragmentProgram = NULL;
|
||||||
cgAvailable = false;
|
cgAvailable = false;
|
||||||
frameCount = 0;
|
frameCount = 0;
|
||||||
|
cgShader = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
COpenGL::~COpenGL(void)
|
COpenGL::~COpenGL(void)
|
||||||
@ -285,6 +286,7 @@ bool COpenGL::Initialize(HWND hWnd)
|
|||||||
cgAvailable = loadCgFunctions();
|
cgAvailable = loadCgFunctions();
|
||||||
if(cgAvailable) {
|
if(cgAvailable) {
|
||||||
cgContext = cgCreateContext();
|
cgContext = cgCreateContext();
|
||||||
|
cgShader = new CGLCG(cgContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
GetClientRect(hWnd,&windowRect);
|
GetClientRect(hWnd,&windowRect);
|
||||||
@ -323,6 +325,10 @@ void COpenGL::DeInitialize()
|
|||||||
if(cgAvailable)
|
if(cgAvailable)
|
||||||
unloadCgLibrary();
|
unloadCgLibrary();
|
||||||
cgAvailable = false;
|
cgAvailable = false;
|
||||||
|
if(cgShader) {
|
||||||
|
delete cgShader;
|
||||||
|
cgShader = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void COpenGL::CreateDrawSurface()
|
void COpenGL::CreateDrawSurface()
|
||||||
@ -402,6 +408,7 @@ void COpenGL::SetupVertices()
|
|||||||
texcoords[5] = 0.0f;
|
texcoords[5] = 0.0f;
|
||||||
texcoords[6] = 0.0f;
|
texcoords[6] = 0.0f;
|
||||||
texcoords[7] = 0.0f;
|
texcoords[7] = 0.0f;
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
|
||||||
}
|
}
|
||||||
|
|
||||||
void COpenGL::Render(SSurface Src)
|
void COpenGL::Render(SSurface Src)
|
||||||
@ -421,6 +428,7 @@ void COpenGL::Render(SSurface Src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(pboFunctionsLoaded) {
|
if(pboFunctionsLoaded) {
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, drawBuffer);
|
||||||
Dst.Surface = (unsigned char *)glMapBuffer(GL_PIXEL_UNPACK_BUFFER,GL_WRITE_ONLY);
|
Dst.Surface = (unsigned char *)glMapBuffer(GL_PIXEL_UNPACK_BUFFER,GL_WRITE_ONLY);
|
||||||
} else {
|
} else {
|
||||||
Dst.Surface = noPboBuffer;
|
Dst.Surface = noPboBuffer;
|
||||||
@ -444,7 +452,16 @@ void COpenGL::Render(SSurface Src)
|
|||||||
ApplyDisplayChanges();
|
ApplyDisplayChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D,drawTexture);
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, quadTextureSize);
|
||||||
|
glTexSubImage2D (GL_TEXTURE_2D,0,0,0,dstRect.right-dstRect.left,dstRect.bottom-dstRect.top,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,pboFunctionsLoaded?0:noPboBuffer);
|
||||||
|
|
||||||
|
if(pboFunctionsLoaded)
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
|
||||||
if (shader_type != OGL_SHADER_NONE) {
|
if (shader_type != OGL_SHADER_NONE) {
|
||||||
|
|
||||||
|
if(shader_type == OGL_SHADER_GLSL) {
|
||||||
GLint location;
|
GLint location;
|
||||||
|
|
||||||
float inputSize[2] = { (float)afterRenderWidth, (float)afterRenderHeight };
|
float inputSize[2] = { (float)afterRenderWidth, (float)afterRenderHeight };
|
||||||
@ -454,8 +471,6 @@ void COpenGL::Render(SSurface Src)
|
|||||||
(float)(GUI.Stretch?windowSize.bottom:afterRenderHeight) };
|
(float)(GUI.Stretch?windowSize.bottom:afterRenderHeight) };
|
||||||
float textureSize[2] = { (float)quadTextureSize, (float)quadTextureSize };
|
float textureSize[2] = { (float)quadTextureSize, (float)quadTextureSize };
|
||||||
float frameCnt = (float)++frameCount;
|
float frameCnt = (float)++frameCount;
|
||||||
|
|
||||||
if(shader_type == OGL_SHADER_GLSL) {
|
|
||||||
location = glGetUniformLocation (shaderProgram, "rubyInputSize");
|
location = glGetUniformLocation (shaderProgram, "rubyInputSize");
|
||||||
glUniform2fv (location, 1, inputSize);
|
glUniform2fv (location, 1, inputSize);
|
||||||
|
|
||||||
@ -465,37 +480,26 @@ void COpenGL::Render(SSurface Src)
|
|||||||
location = glGetUniformLocation (shaderProgram, "rubyTextureSize");
|
location = glGetUniformLocation (shaderProgram, "rubyTextureSize");
|
||||||
glUniform2fv (location, 1, textureSize);
|
glUniform2fv (location, 1, textureSize);
|
||||||
} else if(shader_type == OGL_SHADER_CG) {
|
} else if(shader_type == OGL_SHADER_CG) {
|
||||||
CGparameter cgpModelViewProj = cgGetNamedParameter(cgVertexProgram, "modelViewProj");
|
xySize inputSize = { (float)afterRenderWidth, (float)afterRenderHeight };
|
||||||
|
RECT windowSize, displayRect;
|
||||||
cgGLSetStateMatrixParameter(cgpModelViewProj, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);
|
GetClientRect(hWnd,&windowSize);
|
||||||
|
xySize xywindowSize = { (double)windowSize.right, (double)windowSize.bottom };
|
||||||
#define setProgram2fv(program,varname,floats)\
|
//Get maximum rect respecting AR setting
|
||||||
{\
|
displayRect=CalculateDisplayRect(windowSize.right,windowSize.bottom,windowSize.right,windowSize.bottom);
|
||||||
CGparameter cgp = cgGetNamedParameter(program, varname);\
|
xySize viewportSize = { (double)(displayRect.right - displayRect.left),
|
||||||
if(cgp)\
|
(double)(displayRect.bottom - displayRect.top) };
|
||||||
cgGLSetParameter2fv(cgp,floats);\
|
xySize textureSize = { (double)quadTextureSize, (double)quadTextureSize };
|
||||||
}\
|
cgShader->Render(drawTexture, textureSize, inputSize, viewportSize, xywindowSize);
|
||||||
|
|
||||||
#define setProgram1f(program,varname,val)\
|
|
||||||
{\
|
|
||||||
CGparameter cgp = cgGetNamedParameter(program, varname);\
|
|
||||||
if(cgp)\
|
|
||||||
cgGLSetParameter1f(cgp,val);\
|
|
||||||
}\
|
|
||||||
|
|
||||||
setProgram2fv(cgFragmentProgram,"IN.video_size",inputSize);
|
|
||||||
setProgram2fv(cgFragmentProgram,"IN.texture_size",textureSize);
|
|
||||||
setProgram2fv(cgFragmentProgram,"IN.output_size",outputSize);
|
|
||||||
setProgram1f(cgFragmentProgram,"IN.frame_count",frameCnt);
|
|
||||||
setProgram2fv(cgVertexProgram,"IN.video_size",inputSize);
|
|
||||||
setProgram2fv(cgVertexProgram,"IN.texture_size",textureSize);
|
|
||||||
setProgram2fv(cgVertexProgram,"IN.output_size",outputSize);
|
|
||||||
setProgram1f(cgVertexProgram,"IN.frame_count",frameCnt);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, quadTextureSize);
|
if(GUI.BilinearFilter) {
|
||||||
glTexSubImage2D (GL_TEXTURE_2D,0,0,0,dstRect.right-dstRect.left,dstRect.bottom-dstRect.top,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,pboFunctionsLoaded?0:noPboBuffer);
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
} else {
|
||||||
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
|
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
@ -515,13 +519,6 @@ bool COpenGL::ChangeRenderSize(unsigned int newWidth, unsigned int newHeight)
|
|||||||
|
|
||||||
bool COpenGL::ApplyDisplayChanges(void)
|
bool COpenGL::ApplyDisplayChanges(void)
|
||||||
{
|
{
|
||||||
if(GUI.BilinearFilter) {
|
|
||||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
} else {
|
|
||||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
}
|
|
||||||
if(wglSwapIntervalEXT) {
|
if(wglSwapIntervalEXT) {
|
||||||
wglSwapIntervalEXT(GUI.Vsync?1:0);
|
wglSwapIntervalEXT(GUI.Vsync?1:0);
|
||||||
}
|
}
|
||||||
@ -683,7 +680,9 @@ bool COpenGL::SetShaders(const TCHAR *file)
|
|||||||
SetShadersCG(NULL);
|
SetShadersCG(NULL);
|
||||||
SetShadersGLSL(NULL);
|
SetShadersGLSL(NULL);
|
||||||
shader_type = OGL_SHADER_NONE;
|
shader_type = OGL_SHADER_NONE;
|
||||||
if(file!=NULL && lstrlen(file)>3 && _tcsncicmp(&file[lstrlen(file)-3],TEXT(".cg"),3)==0) {
|
if(file!=NULL && (
|
||||||
|
(lstrlen(file)>3 && _tcsncicmp(&file[lstrlen(file)-3],TEXT(".cg"),3)==0) ||
|
||||||
|
(lstrlen(file)>4 && _tcsncicmp(&file[lstrlen(file)-4],TEXT(".cgp"),4)==0))) {
|
||||||
return SetShadersCG(file);
|
return SetShadersCG(file);
|
||||||
} else {
|
} else {
|
||||||
return SetShadersGLSL(file);
|
return SetShadersGLSL(file);
|
||||||
@ -712,70 +711,15 @@ void COpenGL::checkForCgError(const char *situation)
|
|||||||
|
|
||||||
bool COpenGL::SetShadersCG(const TCHAR *file)
|
bool COpenGL::SetShadersCG(const TCHAR *file)
|
||||||
{
|
{
|
||||||
TCHAR errorMsg[MAX_PATH + 50];
|
|
||||||
HRESULT hr;
|
|
||||||
CGprofile vertexProfile, fragmentProfile;
|
|
||||||
|
|
||||||
if(cgFragmentProgram) {
|
|
||||||
cgDestroyProgram(cgFragmentProgram);
|
|
||||||
cgFragmentProgram = NULL;
|
|
||||||
}
|
|
||||||
if(cgVertexProgram) {
|
|
||||||
cgDestroyProgram(cgVertexProgram);
|
|
||||||
cgVertexProgram = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(cgAvailable) {
|
|
||||||
vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
|
|
||||||
fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
|
|
||||||
|
|
||||||
cgGLDisableProfile(vertexProfile);
|
|
||||||
cgGLDisableProfile(fragmentProfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file == NULL || *file==TEXT('\0'))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if(!cgAvailable) {
|
if(!cgAvailable) {
|
||||||
MessageBox(NULL, TEXT("The CG runtime is unavailable, CG shaders will not run.\nConsult the snes9x readme for information on how to obtain the runtime."), TEXT("CG Error"),
|
MessageBox(NULL, TEXT("The CG runtime is unavailable, CG shaders will not run.\nConsult the snes9x readme for information on how to obtain the runtime."), TEXT("CG Error"),
|
||||||
MB_OK|MB_ICONEXCLAMATION);
|
MB_OK|MB_ICONEXCLAMATION);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cgGLSetOptimalOptions(vertexProfile);
|
if(!cgShader->LoadShader(file))
|
||||||
cgGLSetOptimalOptions(fragmentProfile);
|
|
||||||
|
|
||||||
char *fileContents = ReadShaderFileContents(file);
|
|
||||||
if(!fileContents)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cgVertexProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents,
|
|
||||||
vertexProfile, "main_vertex", NULL);
|
|
||||||
|
|
||||||
checkForCgError("Compiling vertex program");
|
|
||||||
|
|
||||||
cgFragmentProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents,
|
|
||||||
fragmentProfile, "main_fragment", NULL);
|
|
||||||
|
|
||||||
checkForCgError("Compiling fragment program");
|
|
||||||
|
|
||||||
delete [] fileContents;
|
|
||||||
|
|
||||||
if(!cgVertexProgram || !cgFragmentProgram) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(cgVertexProgram) {
|
|
||||||
cgGLEnableProfile(vertexProfile);
|
|
||||||
cgGLLoadProgram(cgVertexProgram);
|
|
||||||
cgGLBindProgram(cgVertexProgram);
|
|
||||||
}
|
|
||||||
if(cgFragmentProgram) {
|
|
||||||
cgGLEnableProfile(fragmentProfile);
|
|
||||||
cgGLLoadProgram(cgFragmentProgram);
|
|
||||||
cgGLBindProgram(cgFragmentProgram);
|
|
||||||
}
|
|
||||||
|
|
||||||
shader_type = OGL_SHADER_CG;
|
shader_type = OGL_SHADER_CG;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -183,6 +183,7 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <gl\gl.h>
|
#include <gl\gl.h>
|
||||||
#include "cgFunctions.h"
|
#include "cgFunctions.h"
|
||||||
|
#include "CGLCG.h"
|
||||||
|
|
||||||
#include "glext.h"
|
#include "glext.h"
|
||||||
#include "wglext.h"
|
#include "wglext.h"
|
||||||
@ -219,6 +220,8 @@ private:
|
|||||||
current_ogl_shader_type shader_type;
|
current_ogl_shader_type shader_type;
|
||||||
bool cgAvailable;
|
bool cgAvailable;
|
||||||
|
|
||||||
|
CGLCG *cgShader;
|
||||||
|
|
||||||
GLuint shaderProgram;
|
GLuint shaderProgram;
|
||||||
GLuint vertexShader;
|
GLuint vertexShader;
|
||||||
GLuint fragmentShader;
|
GLuint fragmentShader;
|
||||||
|
@ -211,6 +211,10 @@ CGGLDP cgGLDisableProfile = NULL;
|
|||||||
CGGLSOO cgGLSetOptimalOptions = NULL;
|
CGGLSOO cgGLSetOptimalOptions = NULL;
|
||||||
CGGLLP cgGLLoadProgram = NULL;
|
CGGLLP cgGLLoadProgram = NULL;
|
||||||
CGGLBP cgGLBindProgram = NULL;
|
CGGLBP cgGLBindProgram = NULL;
|
||||||
|
CGGLSTP cgGLSetTextureParameter = NULL;
|
||||||
|
CGGLETP cgGLEnableTextureParameter = NULL;
|
||||||
|
CGGLSPP cgGLSetParameterPointer = NULL;
|
||||||
|
CGGLECS cgGLEnableClientState = NULL;
|
||||||
|
|
||||||
bool loadCgFunctions()
|
bool loadCgFunctions()
|
||||||
{
|
{
|
||||||
@ -256,6 +260,10 @@ bool loadCgFunctions()
|
|||||||
cgGLSetOptimalOptions = (CGGLSOO)GetProcAddress(hCgGLDll,"cgGLSetOptimalOptions");
|
cgGLSetOptimalOptions = (CGGLSOO)GetProcAddress(hCgGLDll,"cgGLSetOptimalOptions");
|
||||||
cgGLLoadProgram = (CGGLLP)GetProcAddress(hCgGLDll,"cgGLLoadProgram");
|
cgGLLoadProgram = (CGGLLP)GetProcAddress(hCgGLDll,"cgGLLoadProgram");
|
||||||
cgGLBindProgram = (CGGLBP)GetProcAddress(hCgGLDll,"cgGLBindProgram");
|
cgGLBindProgram = (CGGLBP)GetProcAddress(hCgGLDll,"cgGLBindProgram");
|
||||||
|
cgGLSetTextureParameter = (CGGLSTP)GetProcAddress(hCgGLDll,"cgGLSetTextureParameter");
|
||||||
|
cgGLEnableTextureParameter = (CGGLETP)GetProcAddress(hCgGLDll,"cgGLEnableTextureParameter");
|
||||||
|
cgGLSetParameterPointer = (CGGLSPP)GetProcAddress(hCgGLDll,"cgGLSetParameterPointer");
|
||||||
|
cgGLEnableClientState = (CGGLECS)GetProcAddress(hCgGLDll,"cgGLEnableClientState");
|
||||||
|
|
||||||
if(
|
if(
|
||||||
//cg.dll
|
//cg.dll
|
||||||
@ -285,7 +293,11 @@ bool loadCgFunctions()
|
|||||||
!cgGLDisableProfile ||
|
!cgGLDisableProfile ||
|
||||||
!cgGLSetOptimalOptions ||
|
!cgGLSetOptimalOptions ||
|
||||||
!cgGLLoadProgram ||
|
!cgGLLoadProgram ||
|
||||||
!cgGLBindProgram) {
|
!cgGLBindProgram ||
|
||||||
|
!cgGLSetTextureParameter ||
|
||||||
|
!cgGLEnableTextureParameter ||
|
||||||
|
!cgGLSetParameterPointer ||
|
||||||
|
!cgGLEnableClientState) {
|
||||||
unloadCgLibrary();
|
unloadCgLibrary();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -243,7 +243,14 @@ typedef CGGL_API void (CGGLENTRY *CGGLLP)(CGprogram program);
|
|||||||
extern CGGLLP cgGLLoadProgram;
|
extern CGGLLP cgGLLoadProgram;
|
||||||
typedef CGGL_API void (CGGLENTRY *CGGLBP)(CGprogram program);
|
typedef CGGL_API void (CGGLENTRY *CGGLBP)(CGprogram program);
|
||||||
extern CGGLBP cgGLBindProgram;
|
extern CGGLBP cgGLBindProgram;
|
||||||
|
typedef CGGL_API void (CGGLENTRY *CGGLSTP)(CGparameter param, GLuint texobj);
|
||||||
|
extern CGGLSTP cgGLSetTextureParameter;
|
||||||
|
typedef CGGL_API void (CGGLENTRY *CGGLETP)(CGparameter param);
|
||||||
|
extern CGGLETP cgGLEnableTextureParameter;
|
||||||
|
typedef CGGL_API void (CGGLENTRY *CGGLSPP)(CGparameter param, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer);
|
||||||
|
extern CGGLSPP cgGLSetParameterPointer;
|
||||||
|
typedef CGGL_API void (CGGLENTRY *CGGLECS)(CGparameter param);
|
||||||
|
extern CGGLECS cgGLEnableClientState;
|
||||||
|
|
||||||
|
|
||||||
//cgfunctions.cpp
|
//cgfunctions.cpp
|
||||||
|
@ -3129,6 +3129,14 @@
|
|||||||
<Filter
|
<Filter
|
||||||
Name="VideoDriver"
|
Name="VideoDriver"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CCGShader.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CCGShader.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\CDirect3D.cpp"
|
RelativePath=".\CDirect3D.cpp"
|
||||||
>
|
>
|
||||||
@ -3209,6 +3217,14 @@
|
|||||||
RelativePath=".\cgFunctions.h"
|
RelativePath=".\cgFunctions.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CGLCG.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CGLCG.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\COpenGL.cpp"
|
RelativePath=".\COpenGL.cpp"
|
||||||
>
|
>
|
||||||
|
@ -272,27 +272,27 @@ void WinDisplayApplyChanges()
|
|||||||
RECT CalculateDisplayRect(unsigned int sourceWidth,unsigned int sourceHeight,
|
RECT CalculateDisplayRect(unsigned int sourceWidth,unsigned int sourceHeight,
|
||||||
unsigned int displayWidth,unsigned int displayHeight)
|
unsigned int displayWidth,unsigned int displayHeight)
|
||||||
{
|
{
|
||||||
float xFactor;
|
double xFactor;
|
||||||
float yFactor;
|
double yFactor;
|
||||||
float minFactor;
|
double minFactor;
|
||||||
float renderWidthCalc,renderHeightCalc;
|
double renderWidthCalc,renderHeightCalc;
|
||||||
int hExtend = GUI.HeightExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT;
|
int hExtend = GUI.HeightExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT;
|
||||||
float snesAspect = (float)GUI.AspectWidth/hExtend;
|
double snesAspect = (double)GUI.AspectWidth/hExtend;
|
||||||
RECT drawRect;
|
RECT drawRect;
|
||||||
|
|
||||||
if(GUI.Stretch) {
|
if(GUI.Stretch) {
|
||||||
if(GUI.AspectRatio) {
|
if(GUI.AspectRatio) {
|
||||||
//fix for hi-res images with FILTER_NONE
|
//fix for hi-res images with FILTER_NONE
|
||||||
//where we need to correct the aspect ratio
|
//where we need to correct the aspect ratio
|
||||||
renderWidthCalc = (float)sourceWidth;
|
renderWidthCalc = (double)sourceWidth;
|
||||||
renderHeightCalc = (float)sourceHeight;
|
renderHeightCalc = (double)sourceHeight;
|
||||||
if(renderWidthCalc/renderHeightCalc>snesAspect)
|
if(renderWidthCalc/renderHeightCalc>snesAspect)
|
||||||
renderWidthCalc = renderHeightCalc * snesAspect;
|
renderWidthCalc = renderHeightCalc * snesAspect;
|
||||||
else if(renderWidthCalc/renderHeightCalc<snesAspect)
|
else if(renderWidthCalc/renderHeightCalc<snesAspect)
|
||||||
renderHeightCalc = renderWidthCalc / snesAspect;
|
renderHeightCalc = renderWidthCalc / snesAspect;
|
||||||
|
|
||||||
xFactor = (float)displayWidth / renderWidthCalc;
|
xFactor = (double)displayWidth / renderWidthCalc;
|
||||||
yFactor = (float)displayHeight / renderHeightCalc;
|
yFactor = (double)displayHeight / renderHeightCalc;
|
||||||
minFactor = xFactor < yFactor ? xFactor : yFactor;
|
minFactor = xFactor < yFactor ? xFactor : yFactor;
|
||||||
|
|
||||||
drawRect.right = (LONG)(renderWidthCalc * minFactor);
|
drawRect.right = (LONG)(renderWidthCalc * minFactor);
|
||||||
|
@ -200,6 +200,7 @@
|
|||||||
#include "wsnes9x.h"
|
#include "wsnes9x.h"
|
||||||
#include "win32_sound.h"
|
#include "win32_sound.h"
|
||||||
#include "win32_display.h"
|
#include "win32_display.h"
|
||||||
|
#include "CCGShader.h"
|
||||||
#include "../snes9x.h"
|
#include "../snes9x.h"
|
||||||
#include "../memmap.h"
|
#include "../memmap.h"
|
||||||
#include "../cpuexec.h"
|
#include "../cpuexec.h"
|
||||||
@ -7264,7 +7265,7 @@ INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||||||
|
|
||||||
ofn.lStructSize = sizeof(OPENFILENAME);
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
||||||
ofn.hwndOwner = hDlg;
|
ofn.hwndOwner = hDlg;
|
||||||
ofn.lpstrFilter = TEXT("Shader Files\0*.shader;*.cg\0All Files\0*.*\0\0");
|
ofn.lpstrFilter = TEXT("Shader Files\0*.shader;*.cg;*.cgp\0All Files\0*.*\0\0");
|
||||||
ofn.lpstrFile = openFileName;
|
ofn.lpstrFile = openFileName;
|
||||||
ofn.lpstrTitle = TEXT("Select Shader");
|
ofn.lpstrTitle = TEXT("Select Shader");
|
||||||
ofn.lpstrDefExt = TEXT("shader");
|
ofn.lpstrDefExt = TEXT("shader");
|
||||||
@ -7283,7 +7284,7 @@ INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||||||
|
|
||||||
ofn.lStructSize = sizeof(OPENFILENAME);
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
||||||
ofn.hwndOwner = hDlg;
|
ofn.hwndOwner = hDlg;
|
||||||
ofn.lpstrFilter = TEXT("Shader Files\0*.shader;*.cg\0All Files\0*.*\0\0");
|
ofn.lpstrFilter = TEXT("Shader Files\0*.shader;*.cg;*.cgp\0All Files\0*.*\0\0");
|
||||||
ofn.lpstrFile = openFileName;
|
ofn.lpstrFile = openFileName;
|
||||||
ofn.lpstrTitle = TEXT("Select Shader");
|
ofn.lpstrTitle = TEXT("Select Shader");
|
||||||
ofn.lpstrDefExt = TEXT("shader");
|
ofn.lpstrDefExt = TEXT("shader");
|
||||||
|
Loading…
Reference in New Issue
Block a user