Post-processing: Added options to graphics config dialog.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3391 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
d124ceaf92
commit
df91fc8648
|
@ -0,0 +1,6 @@
|
||||||
|
uniform samplerRECT samp0 : register(s0);
|
||||||
|
|
||||||
|
void main(out float4 ocol0 : COLOR0, in float2 uv0 : TEXCOORD0)
|
||||||
|
{
|
||||||
|
ocol0 = (texRECT(samp0, uv0+1).rgba - texRECT(samp0, uv0-1).rgba)*8;
|
||||||
|
}
|
|
@ -67,7 +67,7 @@ bool Copy(const char *srcFilename, const char *destFilename);
|
||||||
|
|
||||||
// creates an empty file filename, returns true on success
|
// creates an empty file filename, returns true on success
|
||||||
bool CreateEmptyFile(const char *filename);
|
bool CreateEmptyFile(const char *filename);
|
||||||
|
|
||||||
// Scans the directory tree gets, starting from _Directory and adds the
|
// Scans the directory tree gets, starting from _Directory and adds the
|
||||||
// results into parentEntry. Returns the number of files+directories found
|
// results into parentEntry. Returns the number of files+directories found
|
||||||
u32 ScanDirectoryTree(const char *directory, FSTEntry& parentEntry);
|
u32 ScanDirectoryTree(const char *directory, FSTEntry& parentEntry);
|
||||||
|
|
|
@ -15,13 +15,21 @@
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
#include <wx/wx.h>
|
||||||
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/filepicker.h>
|
||||||
|
#include <wx/gbsizer.h>
|
||||||
|
#include <wx/notebook.h>
|
||||||
|
#include <wx/mimetype.h>
|
||||||
|
|
||||||
#include "ConfigDlg.h"
|
#include "ConfigDlg.h"
|
||||||
|
#include "FileUtil.h"
|
||||||
#include "../Globals.h"
|
#include "../Globals.h"
|
||||||
#include "../Config.h"
|
#include "../Config.h"
|
||||||
|
|
||||||
#include "../TextureMngr.h"
|
#include "../TextureMngr.h"
|
||||||
#include "VertexShaderManager.h"
|
#include "VertexShaderManager.h"
|
||||||
|
#include "PostProcessing.h"
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
|
BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
|
||||||
EVT_CLOSE(ConfigDialog::OnClose)
|
EVT_CLOSE(ConfigDialog::OnClose)
|
||||||
|
@ -70,6 +78,9 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
|
||||||
EVT_RADIOBUTTON(ID_RADIO_COPYEFBTORAM, ConfigDialog::AdvancedSettingsChanged)
|
EVT_RADIOBUTTON(ID_RADIO_COPYEFBTORAM, ConfigDialog::AdvancedSettingsChanged)
|
||||||
EVT_RADIOBUTTON(ID_RADIO_COPYEFBTOGL, ConfigDialog::AdvancedSettingsChanged)
|
EVT_RADIOBUTTON(ID_RADIO_COPYEFBTOGL, ConfigDialog::AdvancedSettingsChanged)
|
||||||
EVT_CHOICE(ID_PHACKVALUE, ConfigDialog::GeneralSettingsChanged)
|
EVT_CHOICE(ID_PHACKVALUE, ConfigDialog::GeneralSettingsChanged)
|
||||||
|
EVT_CHOICE(ID_POSTSHADER, ConfigDialog::GeneralSettingsChanged)
|
||||||
|
EVT_BUTTON(ID_RELOADSHADER, ConfigDialog::ReloadShaderClick)
|
||||||
|
EVT_BUTTON(ID_EDITSHADER, ConfigDialog::EditShaderClick)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
|
ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
|
||||||
|
@ -260,6 +271,34 @@ void ConfigDialog::CreateGUIControls()
|
||||||
m_ForceFiltering = new wxCheckBox(m_PageGeneral, ID_FORCEFILTERING, wxT("Force bi/trilinear filtering"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
m_ForceFiltering = new wxCheckBox(m_PageGeneral, ID_FORCEFILTERING, wxT("Force bi/trilinear filtering"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
m_ForceFiltering->SetValue(g_Config.bForceFiltering);
|
m_ForceFiltering->SetValue(g_Config.bForceFiltering);
|
||||||
|
|
||||||
|
wxStaticText *PostShaderText = new wxStaticText(m_PageGeneral, ID_POSTSHADERTEXT, wxT("Post-processing shader:"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
|
m_PostShaderCB = new wxChoice(m_PageGeneral, ID_POSTSHADER, wxDefaultPosition, wxDefaultSize, arrayStringFor_PostShaderCB, 0, wxDefaultValidator);
|
||||||
|
m_PostShaderCB->Append(wxT("(off)"));
|
||||||
|
m_ReloadShader = new wxButton(m_PageGeneral, ID_RELOADSHADER, wxT("&Reload"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
m_EditShader = new wxButton(m_PageGeneral, ID_EDITSHADER, wxT("&Edit"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
|
||||||
|
if (File::IsDirectory("User/Shaders"))
|
||||||
|
{
|
||||||
|
File::FSTEntry entry;
|
||||||
|
File::ScanDirectoryTree("User/Shaders", entry);
|
||||||
|
for (int i = 0; i < entry.children.size(); i++)
|
||||||
|
{
|
||||||
|
std::string name = entry.children[i].virtualName.c_str();
|
||||||
|
if (!stricmp(name.substr(name.size() - 4).c_str(), ".txt"))
|
||||||
|
name = name.substr(0, name.size() - 4);
|
||||||
|
m_PostShaderCB->Append(wxT(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
File::CreateDir("User/Shaders");
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString shader = wxT(g_Config.sPostProcessingShader.c_str());
|
||||||
|
if (shader == "")
|
||||||
|
shader = "(off)";
|
||||||
|
m_PostShaderCB->SetStringSelection(shader);
|
||||||
|
|
||||||
// How to use the wxGridBagSizer: The wxGBPosition() must have a column and row
|
// How to use the wxGridBagSizer: The wxGBPosition() must have a column and row
|
||||||
sGeneral = new wxBoxSizer(wxVERTICAL);
|
sGeneral = new wxBoxSizer(wxVERTICAL);
|
||||||
sBasic = new wxGridBagSizer(0, 0);
|
sBasic = new wxGridBagSizer(0, 0);
|
||||||
|
@ -300,6 +339,10 @@ void ConfigDialog::CreateGUIControls()
|
||||||
sEnhancements->Add(MSAAText, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
sEnhancements->Add(MSAAText, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||||
sEnhancements->Add(m_MSAAModeCB, wxGBPosition(1, 1), wxGBSpan(1, 2), wxALL, 5);
|
sEnhancements->Add(m_MSAAModeCB, wxGBPosition(1, 1), wxGBSpan(1, 2), wxALL, 5);
|
||||||
sEnhancements->Add(m_ForceFiltering, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL, 5);
|
sEnhancements->Add(m_ForceFiltering, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL, 5);
|
||||||
|
sEnhancements->Add(PostShaderText, wxGBPosition(3, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||||
|
sEnhancements->Add(m_PostShaderCB, wxGBPosition(3, 1), wxGBSpan(1, 1), wxALL, 5);
|
||||||
|
sEnhancements->Add(m_ReloadShader, wxGBPosition(3, 2), wxGBSpan(1, 1), wxALL, 5);
|
||||||
|
sEnhancements->Add(m_EditShader, wxGBPosition(3, 3), wxGBSpan(1, 1), wxALL, 5);
|
||||||
sbEnhancements->Add(sEnhancements);
|
sbEnhancements->Add(sEnhancements);
|
||||||
sGeneral->Add(sbEnhancements, 0, wxEXPAND|wxALL, 5);
|
sGeneral->Add(sbEnhancements, 0, wxEXPAND|wxALL, 5);
|
||||||
m_PageGeneral->SetSizer(sGeneral);
|
m_PageGeneral->SetSizer(sGeneral);
|
||||||
|
@ -475,6 +518,38 @@ void ConfigDialog::AboutClick(wxCommandEvent& WXUNUSED (event))
|
||||||
_T("Dolphin OGL"), wxOK, this);
|
_T("Dolphin OGL"), wxOK, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfigDialog::ReloadShaderClick(wxCommandEvent& WXUNUSED (event))
|
||||||
|
{
|
||||||
|
PostProcessing::ReloadShader();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigDialog::EditShaderClick(wxCommandEvent& WXUNUSED (event))
|
||||||
|
{
|
||||||
|
if (m_PostShaderCB->GetStringSelection() == "(off)")
|
||||||
|
return;
|
||||||
|
wxString shader = "User/Shaders/" + m_PostShaderCB->GetStringSelection() + ".txt";
|
||||||
|
if (wxFileExists(shader))
|
||||||
|
{
|
||||||
|
wxFileType* filetype = wxTheMimeTypesManager->GetFileTypeFromExtension(_("txt"));
|
||||||
|
if (filetype == NULL) // From extension failed, trying with MIME type now
|
||||||
|
{
|
||||||
|
filetype = wxTheMimeTypesManager->GetFileTypeFromMimeType(_("text/plain"));
|
||||||
|
if (filetype == NULL) // MIME type failed, aborting mission
|
||||||
|
{
|
||||||
|
PanicAlert("Filetype 'txt' is unknown! Will not open!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wxString OpenCommand;
|
||||||
|
OpenCommand = filetype->GetOpenCommand(shader);
|
||||||
|
if (OpenCommand.IsEmpty())
|
||||||
|
PanicAlert("Couldn't find open command for extension 'ini'!");
|
||||||
|
else
|
||||||
|
if (wxExecute(OpenCommand, wxEXEC_ASYNC) == -1)
|
||||||
|
PanicAlert("wxExecute returned -1 on application run!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
|
void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
switch (event.GetId())
|
switch (event.GetId())
|
||||||
|
@ -546,6 +621,11 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
|
||||||
g_Config.UpdateProjectionHack();
|
g_Config.UpdateProjectionHack();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ID_POSTSHADER:
|
||||||
|
g_Config.sPostProcessingShader = m_PostShaderCB->GetString(m_PostShaderCB->GetSelection());
|
||||||
|
if (g_Config.sPostProcessingShader == "(off)")
|
||||||
|
g_Config.sPostProcessingShader = "";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateGUI();
|
UpdateGUI();
|
||||||
|
|
|
@ -84,6 +84,9 @@ class ConfigDialog : public wxDialog
|
||||||
|
|
||||||
wxButton *m_About;
|
wxButton *m_About;
|
||||||
wxButton *m_Close;
|
wxButton *m_Close;
|
||||||
|
wxButton *m_ReloadShader;
|
||||||
|
wxButton *m_EditShader;
|
||||||
|
|
||||||
wxNotebook *m_Notebook;
|
wxNotebook *m_Notebook;
|
||||||
wxPanel *m_PageGeneral;
|
wxPanel *m_PageGeneral;
|
||||||
wxPanel *m_PageAdvanced;
|
wxPanel *m_PageAdvanced;
|
||||||
|
@ -103,7 +106,8 @@ class ConfigDialog : public wxDialog
|
||||||
wxArrayString arrayStringFor_MaxAnisotropyCB;
|
wxArrayString arrayStringFor_MaxAnisotropyCB;
|
||||||
wxChoice *m_MaxAnisotropyCB;
|
wxChoice *m_MaxAnisotropyCB;
|
||||||
wxArrayString arrayStringFor_MSAAModeCB, arrayStringFor_PhackvalueCB;
|
wxArrayString arrayStringFor_MSAAModeCB, arrayStringFor_PhackvalueCB;
|
||||||
wxChoice *m_MSAAModeCB, *m_PhackvalueCB;
|
wxArrayString arrayStringFor_PostShaderCB;
|
||||||
|
wxChoice *m_MSAAModeCB, *m_PhackvalueCB, *m_PostShaderCB;
|
||||||
|
|
||||||
wxCheckBox *m_ShowFPS;
|
wxCheckBox *m_ShowFPS;
|
||||||
wxCheckBox *m_ShaderErrors;
|
wxCheckBox *m_ShaderErrors;
|
||||||
|
@ -194,6 +198,10 @@ class ConfigDialog : public wxDialog
|
||||||
ID_DSTALPHAPASS,
|
ID_DSTALPHAPASS,
|
||||||
ID_RADIO_COPYEFBTORAM,
|
ID_RADIO_COPYEFBTORAM,
|
||||||
ID_RADIO_COPYEFBTOGL,
|
ID_RADIO_COPYEFBTOGL,
|
||||||
|
ID_POSTSHADER,
|
||||||
|
ID_POSTSHADERTEXT,
|
||||||
|
ID_RELOADSHADER,
|
||||||
|
ID_EDITSHADER,
|
||||||
};
|
};
|
||||||
|
|
||||||
void OnClose(wxCloseEvent& event);
|
void OnClose(wxCloseEvent& event);
|
||||||
|
@ -201,6 +209,8 @@ class ConfigDialog : public wxDialog
|
||||||
void UpdateHack();
|
void UpdateHack();
|
||||||
|
|
||||||
void AboutClick(wxCommandEvent& event);
|
void AboutClick(wxCommandEvent& event);
|
||||||
|
void ReloadShaderClick(wxCommandEvent& event);
|
||||||
|
void EditShaderClick(wxCommandEvent& event);
|
||||||
void GeneralSettingsChanged(wxCommandEvent& event);
|
void GeneralSettingsChanged(wxCommandEvent& event);
|
||||||
void AdvancedSettingsChanged(wxCommandEvent& event);
|
void AdvancedSettingsChanged(wxCommandEvent& event);
|
||||||
};
|
};
|
||||||
|
|
|
@ -220,12 +220,8 @@ bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrpr
|
||||||
const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
|
const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
|
||||||
CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts);
|
CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts);
|
||||||
if (!cgIsProgram(tempprog) || cgGetError() != CG_NO_ERROR) {
|
if (!cgIsProgram(tempprog) || cgGetError() != CG_NO_ERROR) {
|
||||||
if (s_displayCompileAlert) {
|
|
||||||
PanicAlert("Failed to create pixel shader");
|
|
||||||
s_displayCompileAlert = false;
|
|
||||||
}
|
|
||||||
cgDestroyProgram(tempprog);
|
cgDestroyProgram(tempprog);
|
||||||
ERROR_LOG(VIDEO, "Failed to create ps %s:", cgGetLastListing(g_cgcontext));
|
ERROR_LOG(VIDEO, "Failed to compile ps %s:", cgGetLastListing(g_cgcontext));
|
||||||
ERROR_LOG(VIDEO, pstrprogram);
|
ERROR_LOG(VIDEO, pstrprogram);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,16 +38,20 @@ void Shutdown()
|
||||||
s_shader.Destroy();
|
s_shader.Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyShader()
|
void ReloadShader()
|
||||||
|
{
|
||||||
|
s_currentShader = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ApplyShader()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
|
||||||
if (GetAsyncKeyState(VK_LSHIFT))
|
|
||||||
s_currentShader = "";
|
|
||||||
#endif
|
|
||||||
if (s_currentShader != "User/Shaders/" + g_Config.sPostProcessingShader + ".txt")
|
if (s_currentShader != "User/Shaders/" + g_Config.sPostProcessingShader + ".txt")
|
||||||
{
|
{
|
||||||
// Set immediately to prevent endless recompiles on failure.
|
// Set immediately to prevent endless recompiles on failure.
|
||||||
s_currentShader = "User/Shaders/" + g_Config.sPostProcessingShader + ".txt";
|
if (!g_Config.sPostProcessingShader.empty())
|
||||||
|
s_currentShader = "User/Shaders/" + g_Config.sPostProcessingShader + ".txt";
|
||||||
|
else
|
||||||
|
s_currentShader.clear();
|
||||||
|
|
||||||
s_shader.Destroy();
|
s_shader.Destroy();
|
||||||
|
|
||||||
|
@ -66,22 +70,20 @@ void ApplyShader()
|
||||||
ERROR_LOG(VIDEO, "Failed to load post-processing shader %s - does not exist?", s_currentShader.c_str());
|
ERROR_LOG(VIDEO, "Failed to load post-processing shader %s - does not exist?", s_currentShader.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
ERROR_LOG(VIDEO, "No post-processing shader selected.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_shader.glprogid == 0)
|
if (s_shader.glprogid != 0)
|
||||||
{
|
{
|
||||||
ERROR_LOG(VIDEO, "WTF");
|
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||||
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, s_shader.glprogid);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
glDisable(GL_FRAGMENT_PROGRAM_ARB);
|
||||||
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
// If anything went wrong above, glprogid will be 0, which is OK.
|
|
||||||
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, s_shader.glprogid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -27,7 +27,9 @@ namespace PostProcessing
|
||||||
void Init();
|
void Init();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
void ApplyShader();
|
void ReloadShader();
|
||||||
|
// Returns false if no shader was applied.
|
||||||
|
bool ApplyShader();
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
|
@ -179,10 +179,10 @@ void SetDefaultRectTexParams()
|
||||||
|
|
||||||
void HandleCgError(CGcontext ctx, CGerror err, void* appdata)
|
void HandleCgError(CGcontext ctx, CGerror err, void* appdata)
|
||||||
{
|
{
|
||||||
ERROR_LOG(VIDEO, "Cg error: %s", cgGetErrorString(err));
|
DEBUG_LOG(VIDEO, "Cg error: %s", cgGetErrorString(err));
|
||||||
const char* listing = cgGetLastListing(g_cgcontext);
|
const char* listing = cgGetLastListing(g_cgcontext);
|
||||||
if (listing != NULL) {
|
if (listing != NULL) {
|
||||||
ERROR_LOG(VIDEO, " last listing: %s", listing);
|
DEBUG_LOG(VIDEO, " last listing: %s", listing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -957,15 +957,28 @@ void Renderer::Swap(const TRectangle& rc)
|
||||||
glDrawArrays(GL_QUADS, 0, 4);
|
glDrawArrays(GL_QUADS, 0, 4);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Here's an opportunity to bind a fragment shader to do post processing.
|
// We must call ApplyShader here even if no post proc is selected - it takes
|
||||||
PostProcessing::ApplyShader();
|
// care of disabling it in that case. It returns false in case of no post processing.
|
||||||
|
if (PostProcessing::ApplyShader())
|
||||||
|
{
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glTexCoord2f(0, v_min); glMultiTexCoord2fARB(GL_TEXTURE1, 0, 0); glVertex2f(-1, -1);
|
||||||
|
glTexCoord2f(0, v_max); glMultiTexCoord2fARB(GL_TEXTURE1, 0, 1); glVertex2f(-1, 1);
|
||||||
|
glTexCoord2f(u_max, v_max); glMultiTexCoord2fARB(GL_TEXTURE1, 1, 1); glVertex2f( 1, 1);
|
||||||
|
glTexCoord2f(u_max, v_min); glMultiTexCoord2fARB(GL_TEXTURE1, 1, 0); glVertex2f( 1, -1);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
|
||||||
glTexCoord2f(0, v_min); glMultiTexCoord2fARB(GL_TEXTURE1, 0, 0); glVertex2f(-1, -1);
|
}
|
||||||
glTexCoord2f(0, v_max); glMultiTexCoord2fARB(GL_TEXTURE1, 0, 1); glVertex2f(-1, 1);
|
else
|
||||||
glTexCoord2f(u_max, v_max); glMultiTexCoord2fARB(GL_TEXTURE1, 1, 1); glVertex2f( 1, 1);
|
{
|
||||||
glTexCoord2f(u_max, v_min); glMultiTexCoord2fARB(GL_TEXTURE1, 1, 0); glVertex2f( 1, -1);
|
glBegin(GL_QUADS);
|
||||||
glEnd();
|
glTexCoord2f(0, v_min); glVertex2f(-1, -1);
|
||||||
|
glTexCoord2f(0, v_max); glVertex2f(-1, 1);
|
||||||
|
glTexCoord2f(u_max, v_max); glVertex2f( 1, 1);
|
||||||
|
glTexCoord2f(u_max, v_min); glVertex2f( 1, -1);
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||||
TextureMngr::DisableStage(0);
|
TextureMngr::DisableStage(0);
|
||||||
|
|
Loading…
Reference in New Issue