Works fine here.
Try changing
Shader.SetParameter('colorMap', GL_TEXTURE0_ARB);
to
Shader.SetParameter('colorMap', Textures[0]);
That might work, as I think it's the texture ID you need to pass in there not the opengl constant.
Works fine here.
Try changing
Shader.SetParameter('colorMap', GL_TEXTURE0_ARB);
to
Shader.SetParameter('colorMap', Textures[0]);
That might work, as I think it's the texture ID you need to pass in there not the opengl constant.
<A HREF="http://www.myhpf.co.uk/banner.asp?friend=139328">
<br /><IMG SRC="http://www.myhpf.co.uk/banners/60x468.gif" BORDER="0">
<br /></A>
Umm... No?
Aren't you supposed to pass the id of the texture unit, that has the texture binded, to use as sampler2D object in the shader, not the texture itself?
I tried that too and it doesn't work any better...
Any chance that you could post some kind of simple example using the shaders ie. a complete program? So that I could compare it to my code and see what's the difference and where it goes wrong...
If you develop an idiot proof system, the nature develops better idiots.
I'll try to make as simple program as possible using shaders and see if it still produces the error.
EDIT: Here's the program.
The shader class:
[pascal]
unit uShader;
{
Project Miniverse
http://www.projectminiverse.com
Description:
GLSL shader object
Classes:
TShader
Created:
22.04.2006 (JA)
Modified:
}
interface
uses
{$IFDEF USE_SDL}
GL, GLU, GLEXT,
{$ELSE}
dglOpenGL,
{$ENDIF}
glGeometry;
type
TShader = class(TObject)
protected
FProgramObject: GLHandleARB;
FName: String;
FResult: String;
public
constructor Create(FileName: String); overload;
constructor Create(const Name, VertexProgram, FragmentProgram: String); overload;
destructor Destroy; override;
function CheckForErrors(glObject: GLHandleARB): String;
function LoadFragmentandVertexShader(FFilename: string; VFilename: string): GLHandleARB;
procedure Enable;
procedure Disable;
procedure SetParameter(const Name: String; Value: TInt); overload;
procedure SetParameter(const Name: String; Value: TFloat); overload;
procedure SetParameter(const Name: String; Value1, Value2, Value3, Value4: TFloat); overload;
property Name: String read FName;
property ProgramObject: GLHandleARB read FProgramObject;
property Result: String read FResult;
end;
implementation
uses
Classes,
SysUtils,
glUtils;
constructor TShader.Create(FileName: String);
begin
inherited Create;
end;
constructor TShader.Create(const Name, VertexProgram, FragmentProgram: String);
begin
inherited Create;
FName := Name;
FProgramObject := LoadFragmentandVertexShader(FragmentProgram, VertexProgram);
FResult := CheckForErrors(FProgramObject);
glCheckForError();
end;
destructor TShader.Destroy;
begin
inherited Destroy;
end;
function TShader.CheckForErrors(glObject: GLHandleARB): String;
var
blen, slen: GLInt;
InfoLog : PGLCharARB;
begin
glGetObjectParameterivARB(glObject, GL_OBJECT_INFO_LOG_LENGTH_ARB, @blen);
if blen > 1 then
begin
GetMem(InfoLog, blen*SizeOf(GLCharARB));
{$IFDEF USE_SDL}
glGetInfoLogARB(glObject, blen , @slen, InfoLog);
{$ELSE}
glGetInfoLogARB(glObject, blen , slen, InfoLog);
{$ENDIF}
Result:= PChar(InfoLog);
Dispose(InfoLog);
end;
end;
function TShader.LoadFragmentandVertexShader(FFilename: string; VFilename: string): GLHandleARB;
var
ProgramObject, FragmentShaderObject, VertexShaderObject: GLHandleARB;
FShader: TStringList;
FShaderText: String;
FShaderLength: Integer;
VShader: TStringList;
VShaderText: String;
VShaderLength: Integer;
begin
Result := 0;
if FileExists(FFilename) then
if FileExists(VFilename) then
begin
ProgramObject := glCreateProgramObjectARB;
FragmentShaderObject := glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
VertexShaderObject := glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
FShader := TStringList.Create;
FShader.LoadFromFile(FFilename);
FShaderText := FShader.Text;
FShaderLength := Length(FShaderText);
VShader := TStringList.Create;
VShader.LoadFromFile(VFilename);
VShaderText := VShader.Text;
VShaderLength := Length(VShaderText);
glShaderSourceARB(VertexShaderObject, 1, @VShaderText, @VShaderLength);
glShaderSourceARB(FragmentShaderObject, 1, @FShaderText, @FShaderLength);
glCompileShaderARB(FragmentShaderObject);
glCompileShaderARB(VertexShaderObject);
glAttachObjectARB(ProgramObject, FragmentShaderObject);
glAttachObjectARB(ProgramObject, VertexShaderObject);
glDeleteObjectARB(FragmentShaderObject);
glDeleteObjectARB(VertexShaderObject);
glLinkProgramARB(ProgramObject);
Result := ProgramObject;
end;
end;
procedure TShader.Enable;
begin
glUseProgramObjectARB(FProgramObject);
end;
procedure TShader.Disable;
begin
glUseProgramObjectARB(0);
end;
procedure TShader.SetParameter(const Name: String; Value: TInt);
var
p: PGLcharARB;
begin
p := PGLCharArb(Name);
glUniform1iARB(glGetUniformLocationARB(FProgramObj ect, p), Value);
end;
procedure TShader.SetParameter(const Name: String; Value: TFloat);
var
p: PGLcharARB;
begin
p := PGLCharARB(Name);
glUniform1fARB(glGetUniformLocationARB(FProgramObj ect, p), Value);
end;
procedure TShader.SetParameter(const Name: String; Value1, Value2, Value3, Value4: TFloat);
var
p: PGLcharARB;
begin
p := PGLCharARB(Name);
glUniform4fARB(glGetUniformLocationARB(FProgramObj ect, p), Value1, Value2, Value3, Value4);
end;
end.
[/pascal]
And the test program:
[pascal]
program SDL_OpenGLTest;
uses
SysUtils,
GL, GLU, GLEXT,
SDL,
Windows,
uShader,
uTextureManager;
const
// screen width, height, and bit depth
SCREEN_WIDTH = 640;
SCREEN_HEIGHT = 480;
SCREEN_BPP = 32;
MAX_EXTENSION = 4;
Extensions: array [0..MAX_EXTENSION] of String = (
'GL_ARB_multitexture',
'GL_ARB_texture_cube_map',
'GL_ARB_fragment_shader',
'GL_ARB_vertex_shader',
'GL_ARB_shader_objects'
);
type
EOpenGLError = class(Exception);
var
// This is our SDL surface
surface : PSDL_Surface;
Ready: Boolean;
Shader: TShader;
Textures: array [0..1] of GLuInt;
procedure glCheckForError;
var
glError: GLenum;
begin
glError := glGetError();
if (glError <> GL_NO_ERROR) then
raise EOpenGLError.Create('OpenGL error! Code: ' + IntToStr(glError) + ' ($' + IntToHex(glError, 4) + ' hex) Description: ' + gluErrorString(glError));
end;
procedure TerminateApplication;
begin
SDL_QUIT;
Halt(0);
end;
procedure HandleError(ErrClass: String; ErrException: Exception; ErrMethod: String);
begin
Ready := FALSE;
MessageBox(0, PChar('Class: ' + ErrClass + #13#10 + 'Method: ' + ErrMethod + #13#10 + 'Exception: ' + ErrException.ClassName + #13#10 + 'Message: ' + ErrException.Message), 'Error!', MB_ICONERROR or MB_OK);
TerminateApplication;
end;
// function to reset our viewport after a window resize
function ResizeWindow( width : integer; height : integer ) : Boolean;
var
h: Integer;
begin
try
// Protect against a divide by zero
if (Height = 0) then
h := 1
else
h := Height;
// Setup our viewport.
glViewport( 0, 0, Width, h );
// Change to the projection matrix and set our viewing volume.
glMatrixMode( GL_PROJECTION );
glLoadIdentity;
// Set our perspective
gluPerspective( 45.0, Width / h, 0.1, 1000.0 );
// Make sure we're changing the model view and not the projection
glMatrixMode( GL_MODELVIEW );
// Reset The View
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
Result := TRUE;
except
raise;
end;
end;
// function to handle key press events
procedure HandleKeyPress( keysym : PSDL_keysym );
begin
case keysym^.sym of
SDLK_ESCAPE :
// ESC key was pressed
TerminateApplication;
end;
end;
// A general OpenGL initialization function. Sets all of the initial parameters.
procedure InitGL;
// We call this right after our OpenGL window is created.
var
s: String;
i: Integer;
begin
gTextureManager := TTextureManager.Create;
if not glext_LoadExtension('GL_version_1_2') then
s := 'OpenGL version 1.2 not supported!' + #13#10;
// Load extensions
for i := 0 to MAX_EXTENSION do
if glext_ExtensionSupported(PChar(Extensions[i]), #0) then
glext_LoadExtension(Extensions[i])
else
s := Extensions[i] + #13#10;
if s <> '' then
raise EOpenGLError('All needed OpenGL extensions are not supported! Unsupported extensions: ' + #13#10 + s);
glClearColor(0.0, 0.0, 0.0, 0.0);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
glShadeModel(GL_SMOOTH);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
glCheckForError();
Textures[0] := gTextureManager.GetTexture('Data\Textures\Misc\Che cker.bmp');
Textures[1] := gTextureManager.GetTexture('Data\Textures\Misc\Ope nGL.bmp');
Shader := TShader.Create('SimpleShader', 'Shaders\texture.vp', 'Shaders\texture.fp');
glCheckForError();
ResizeWindow(SCREEN_WIDTH, SCREEN_HEIGHT);
Ready := TRUE;
end;
// The main drawing function.
procedure DrawGLScene;
begin
if not Ready then
Exit;
try
glClear( GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT or GL_STENCIL_BUFFER_BIT );
glLoadIdentity();
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, Textures[0]);
//glActiveTextureARB(GL_TEXTURE1_ARB);
//glEnable(GL_TEXTURE_2D);
//glBindTexture(GL_TEXTURE_2D, Textures[1]);
//glCheckForError();
Shader.Enable;
glCheckForError();
Shader.SetParameter('colorMap', GL_TEXTURE0_ARB);
glCheckForError();
glColor3f(1, 1, 1);
glBegin(GL_QUADS);
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1, 0);
//glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 0);
glVertex3f(10, -10, -30);
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1, 1);
//glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 1);
glVertex3f(10, 10, -30);
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, 1);
//glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 1);
glVertex3f(-10, 10, -30);
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, 0);
//glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 0);
glVertex3f(-10, -10, -30);
glEnd();
glCheckForError();
Shader.Disable;
// swap buffers to display, since we're double buffered.
SDL_GL_SwapBuffers;
except
on E: Exception do
HandleError('Application', E, 'DrawGLScene');
end;
end;
var
Done : Boolean;
event : TSDL_Event;
videoflags : Uint32;
videoInfo : PSDL_VideoInfo;
begin
// Initialize SDL
if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) then
begin
TerminateApplication;
end;
// Fetch the video info
videoInfo := SDL_GetVideoInfo;
if ( videoInfo = nil ) then
begin
TerminateApplication;
end;
// the flags to pass to SDL_SetVideoMode
videoFlags := SDL_OPENGL; // Enable OpenGL in SDL
videoFlags := videoFlags or SDL_DOUBLEBUF; // Enable double buffering
videoFlags := videoFlags or SDL_HWPALETTE; // Store the palette in hardware
// This checks to see if surfaces can be stored in memory
if ( videoInfo^.hw_available <> 0 ) then
videoFlags := videoFlags or SDL_HWSURFACE
else
videoFlags := videoFlags or SDL_SWSURFACE;
// This checks if hardware blits can be done * /
if ( videoInfo^.blit_hw <> 0 ) then
videoFlags := videoFlags or SDL_HWACCEL;
// Set the OpenGL Attributes
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
// Set the title bar in environments that support it
SDL_WM_SetCaption( 'SDL OpenGL test', nil );
videoflags := videoFlags or SDL_RESIZABLE; // Enable window resizing
//videoflags := videoFlags or SDL_FULLSCREEN; // Enable window resizing
surface := SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, videoflags );
if ( surface = nil ) then
begin
TerminateApplication;
end;
InitGL;
// Loop, drawing and checking events
Done := FALSE;
while ( not Done ) do
begin
// This could go in a separate function
while ( SDL_PollEvent( @event ) = 1 ) do
begin
case event.type_ of
SDL_QUITEV :
begin
Done := true;
end;
SDL_KEYDOWN :
begin
// handle key presses
HandleKeyPress( @event.key.keysym );
end;
SDL_VIDEORESIZE :
begin
surface := SDL_SetVideoMode( event.resize.w, event.resize.h, SCREEN_BPP, videoflags );
if ( surface = nil ) then
begin
TerminateApplication;
end;
ResizeWindow( event.resize.w, event.resize.h );
end;
end;
end;
// draw the scene
DrawGLScene;
end;
TerminateApplication;
end.
[/pascal]
The TextureManager class loads/saves/caches the textures, you can replace it with something similar (it would be too big to post here).
Any ideas why it doesn't work?
If you develop an idiot proof system, the nature develops better idiots.
The texture units are indexed from 0 to n -1 where n is the number of avaiable texture units.
So to use first unit send 0 instad of GL_TEXTURE0_ARB and everything should be okay.
Yes! That's it! Now it works!
Thanks a lot.
If you develop an idiot proof system, the nature develops better idiots.
Bookmarks