Code: Select all
// bikplayer.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include "bink.h"
#include "GLee.h"
#include <gl/gl.h>
#include <gl/glu.h>
#include "glut.h"
#include <malloc.h>
//#include <Carbon/Carbon.h>
static GLuint s_Textures[4];
static HBINK s_Bink = 0;
static char* s_TextureMem = 0;
static char* s_TextOutMem = 0;
static S32 s_HasAlpha = 0;
static S32 s_TextureWidth = 0;
static S32 s_TextureHeight = 0;
// Shader stuff
static S32 s_UseShaders = 0;
static GLhandleARB s_Program = 0;
static GLhandleARB s_VertShader = 0;
static GLhandleARB s_FragShader = 0;
static S32 s_YTexIndex = 0;
static S32 s_cRTexIndex = 0;
static S32 s_cBTexIndex = 0;
static S32 s_ATexIndex = 0;
int gluCheckExtension( const U8 * pstofind, const unsigned char * pstrext )
{
char * psub = strstr( (char*) pstrext, (const char *) pstofind);
return (psub - (char *) pstrext);
}
#ifdef _DEBUG
#define GLCHK CheckGLError()
char errbuff[256];
void CheckGLError()
{
GLenum en = glGetError();
if ( en != GL_NO_ERROR )
{
sprintf( errbuff, "GL Error %u", en );
OutputDebugString( errbuff );
}
}
#else
#define GLCHK
#endif
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
S32 Shader_CheckCaps()
{
const unsigned char* extensions = glGetString(GL_EXTENSIONS);
if (gluCheckExtension((const U8*)"GL_ARB_shader_objects", extensions) == 0) return 0;
if (gluCheckExtension((const U8*)"GL_ARB_vertex_shader", extensions) == 0) return 0;
if (gluCheckExtension((const U8*)"GL_ARB_fragment_shader", extensions) == 0) return 0;
if (gluCheckExtension((const U8*)"GL_ARB_shading_language_100", extensions) == 0) return 0;
return 1;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
S32 Shader_Link(GLhandleARB i_Shader)
{
S32 Success = 0;
glLinkProgramARB(i_Shader);
GLCHK;
if (glGetError() != GL_NO_ERROR) return 0;
glGetObjectParameterivARB(i_Shader, GL_OBJECT_LINK_STATUS_ARB, &Success);
GLCHK;
if (Success == 0) return 0;
return 1;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
S32 Shader_Compile(S32 i_Target, char* i_Source, GLhandleARB* o_Shader)
{
if (i_Source == 0) return 0;
*o_Shader = glCreateShaderObjectARB(i_Target);
GLCHK;
if (glGetError() != GL_NO_ERROR)
return 0;
glShaderSourceARB(*o_Shader, 1, (const char**)&i_Source, 0);
GLCHK;
if (glGetError() != GL_NO_ERROR)
return 0;
glCompileShaderARB(*o_Shader);
GLCHK;
if (glGetError() != GL_NO_ERROR)
return 0;
{
S32 Success = 0;
glGetObjectParameterivARB(*o_Shader, GL_OBJECT_COMPILE_STATUS_ARB, &Success);
GLCHK;
if (Success == 0)
return 0;
}
return 1;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
S32 Shader_BuildOurShaders()
{
char VertexShader[] =
"void main(void)\n"
"{\n"
" gl_TexCoord[0] = gl_MultiTexCoord0;\n"
" gl_Position = ftransform();\n"
"}\n";
char FragmentShader[] =
"uniform sampler2D YTex;\n"
"uniform sampler2D cRTex;\n"
"uniform sampler2D cBTex;\n"
"uniform sampler2D ATex;\n"
"void main (void)\n"
"{\n"
" const vec4 crc = vec4(1.595, -0.813, 0, 0);\n"
" const vec4 crb = vec4(0, -0.391, 2.017, 0);\n"
" const vec4 adj = vec4(-0.870, 0.529, -1.0816, 0);\n"
" float Y = texture2D(YTex, gl_TexCoord[0].st).x;\n"
" float cR = texture2D(cRTex, gl_TexCoord[0].st).x;\n"
" float cB = texture2D(cBTex, gl_TexCoord[0].st).x;\n"
" float A = texture2D(ATex, gl_TexCoord[0].st).x;\n"
" vec4 p;\n"
" p = vec4(Y * 1.164, Y * 1.164, Y * 1.164, 1);\n"
" p += crc * cR;\n"
" p += crb * cB;\n"
" p += adj;\n"
" p.w = A;\n"
" gl_FragColor = p;\n"
"}\n";
if (Shader_Compile(GL_VERTEX_SHADER_ARB, VertexShader, &s_VertShader) == 0)
{
printf("Couldn't compile vertex shader.\n");
return 0;
}
if (Shader_Compile(GL_FRAGMENT_SHADER_ARB, FragmentShader, &s_FragShader) == 0)
{
printf("Couldn't compile fragment shader.\n");
return 0;
}
s_Program = glCreateProgramObjectARB();
GLCHK;
glAttachObjectARB(s_Program, s_VertShader);
GLCHK;
glAttachObjectARB(s_Program, s_FragShader);
GLCHK;
if (Shader_Link(s_Program) == 0)
{
printf("Couldn't link shader.\n");
return 0;
}
glUseProgramObjectARB(s_Program);
GLCHK;
s_YTexIndex = glGetUniformLocationARB(s_Program, "YTex");
GLCHK;
s_cRTexIndex = glGetUniformLocationARB(s_Program, "cRTex");
GLCHK;
s_cBTexIndex = glGetUniformLocationARB(s_Program, "cBTex");
GLCHK;
s_ATexIndex = glGetUniformLocationARB(s_Program, "ATex");
GLCHK;
return 1;
}
DWORD dwtotcalls = 0;
DWORD dwbikcopy = 0;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void RenderBinkVid()
{
char buffer[256];
glClearColor(0, 0, 1, 1);
GLCHK;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLCHK;
dwtotcalls++;
int ic1 = 0, ic2 = 0;
if (!BinkWait(s_Bink))
{
BinkDoFrame(s_Bink);
dwbikcopy++;
if (s_UseShaders)
{
glActiveTextureARB(GL_TEXTURE0_ARB);
GLCHK;
glUniform1iARB(s_YTexIndex, 0);
GLCHK;
glBindTexture(GL_TEXTURE_2D, s_Textures[0]);
GLCHK;
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, s_TextureWidth, s_TextureHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, s_Bink->FrameBuffers->Frames[s_Bink->FrameBuffers->FrameNum].YPlane.Buffer);
GLCHK;
glActiveTextureARB(GL_TEXTURE1_ARB);
glUniform1iARB(s_cRTexIndex, 1);
glBindTexture(GL_TEXTURE_2D, s_Textures[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, s_TextureWidth/2, s_TextureHeight/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, s_Bink->FrameBuffers->Frames[s_Bink->FrameBuffers->FrameNum].cRPlane.Buffer);
glActiveTextureARB(GL_TEXTURE2_ARB);
glUniform1iARB(s_cBTexIndex, 2);
glBindTexture(GL_TEXTURE_2D, s_Textures[2]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, s_TextureWidth/2, s_TextureHeight/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, s_Bink->FrameBuffers->Frames[s_Bink->FrameBuffers->FrameNum].cBPlane.Buffer);
if (s_HasAlpha)
{
glActiveTextureARB(GL_TEXTURE3_ARB);
glUniform1iARB(s_ATexIndex, 3);
glBindTexture(GL_TEXTURE_2D, s_Textures[3]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, s_TextureWidth, s_TextureHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, s_Bink->FrameBuffers->Frames[s_Bink->FrameBuffers->FrameNum].APlane.Buffer);
}
sprintf(buffer, "Bink Frame = %d of %d > Totcalls = %u Binkcalls = %u\n", s_Bink->FrameNum, s_Bink->Frames, dwtotcalls, dwbikcopy );
OutputDebugString( buffer );
}
else
{
char buffer[256];
S32 bc = BinkCopyToBuffer(s_Bink, s_TextureMem, s_TextureWidth*4, s_Bink->Height, 0, 0, (s_HasAlpha ? BINKSURFACE32RA : BINKSURFACE32R));
sprintf(buffer, "Bink Frame = %d of %d > Bink copy = %d - Totcalls = %u Binkcalls = %u\n", s_Bink->FrameNum, s_Bink->Frames, bc, dwtotcalls, dwbikcopy );
OutputDebugString( buffer );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, s_TextureWidth, s_TextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, s_TextureMem);
GLCHK;
}
BinkNextFrame(s_Bink);
}
else
{
Sleep( 10 ); // 1000
}
float verts[] = {
-1, -1,
1, -1,
-1, 1,
1, 1,
};
float v = s_Bink->Height / (float)s_TextureHeight;
float u = s_Bink->Width / (float)s_TextureWidth;
float uvs[] = {
0, v,
u, v,
0, 0,
u, 0
};
glVertexPointer(2, GL_FLOAT, 0, verts);
GLCHK;
if (s_UseShaders)
{
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, uvs);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, uvs);
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, uvs);
if (s_HasAlpha)
{
glClientActiveTextureARB(GL_TEXTURE3_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, uvs);
}
}
else
{
glTexCoordPointer(2, GL_FLOAT, 0, uvs);
GLCHK;
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
GLCHK;
glFlush();
GLCHK;
glutSwapBuffers();
GLCHK;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int _tmain( int argc, char* argv[] )
{
S32 ForceBlit = 1;
if (argc == 1)
{
printf("Specify BINK video on the command line to play.\n");
return 0;
}
int ilen = strlen( argv[1]);
s_Bink = BinkOpen(argv[1], BINKALPHA);
if (s_Bink == 0)
{
printf("Couldn't open %s\n", argv[1]);
return 0;
}
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(s_Bink->Width, s_Bink->Height);
glutCreateWindow("OpenGL Bink");
glutDisplayFunc(RenderBinkVid);
glutIdleFunc(RenderBinkVid);
glGenTextures(4, s_Textures);
GLCHK;
s_HasAlpha = s_Bink->FrameBuffers[0].Frames[0].APlane.Allocate;
if (s_HasAlpha)
{
glEnable(GL_BLEND);
GLCHK;
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
GLCHK;
}
//
// Check for shader caps.
//
s_UseShaders = Shader_CheckCaps() && !ForceBlit;
if (s_UseShaders)
{
if (Shader_BuildOurShaders() == 0)
{
s_UseShaders = 0;
}
else
{
// Setup the other texture units.
glActiveTextureARB(GL_TEXTURE0_ARB);
GLCHK;
glEnable(GL_TEXTURE_2D);
GLCHK;
glBindTexture(GL_TEXTURE_2D, s_Textures[0]);
GLCHK;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
GLCHK;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GLCHK;
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
GLCHK;
glActiveTextureARB(GL_TEXTURE1_ARB);
GLCHK;
glEnable(GL_TEXTURE_2D);
GLCHK;
glBindTexture(GL_TEXTURE_2D, s_Textures[1]);
GLCHK;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
GLCHK;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GLCHK;
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
GLCHK;
glActiveTextureARB(GL_TEXTURE2_ARB);
GLCHK;
glEnable(GL_TEXTURE_2D);
GLCHK;
glBindTexture(GL_TEXTURE_2D, s_Textures[2]);
GLCHK;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
GLCHK;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GLCHK;
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
GLCHK;
if (s_HasAlpha)
{
glActiveTextureARB(GL_TEXTURE3_ARB);
GLCHK;
glEnable(GL_TEXTURE_2D);
GLCHK;
glBindTexture(GL_TEXTURE_2D, s_Textures[3]);
GLCHK;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
GLCHK;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GLCHK;
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
GLCHK;
}
}
}
s_TextureHeight = s_Bink->Height;
s_TextureWidth = s_Bink->Width;
// Only allocate the blit space if we aren't using shaders.
if (s_UseShaders == 0)
{
s_TextureMem = (char *) malloc(s_TextureWidth * s_TextureHeight * 4);
s_TextOutMem = (char *) malloc(s_TextureWidth * s_TextureHeight * 4);
memset(s_TextureMem, 0, s_TextureWidth * s_TextureHeight * 4);
memset(s_TextOutMem, 0, s_TextureWidth * s_TextureHeight * 4);
glEnable(GL_TEXTURE_2D);
GLCHK;
glBindTexture(GL_TEXTURE_2D, s_Textures[0]);
GLCHK;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
GLCHK;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GLCHK;
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
GLCHK;
}
glEnableClientState(GL_VERTEX_ARRAY);
GLCHK;
glutMainLoop();
if (s_TextureMem) free(s_TextureMem);
glDeleteTextures(4, s_Textures);
BinkClose(s_Bink);
s_Bink = 0;
s_TextureMem = 0;
char buff[256];
sprintf(buff, "Total = %u Bik=%u", dwtotcalls, dwbikcopy );
OutputDebugString( buff );
return 0;
}
I've added the following :
Code: Select all
s32 s_UseShaders = false;
video::IVideoDriver * driver = NULL;
video::ITexture * yTex = NULL;
video::ITexture * cRTex = NULL;
video::ITexture * cBTex = NULL;
video::ITexture * ATex = NULL;
video::ITexture * pblt = NULL;
void RenderBinkVid( video::IMaterialRendererServices* services )
{
glClearColor(0, 0, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLint tids[4] = {0, 1, 2, 3 };
S32 s_TextureWidth = s_Bink->Width;
S32 s_TextureHeight = s_Bink->Height;
size_t tsize = s_Bink->Width * s_Bink->Height;
if (!BinkWait(s_Bink))
{
BinkDoFrame(s_Bink);
if (s_UseShaders)
{
glActiveTextureARB(GL_TEXTURE0_ARB);
//glUniform1iARB(s_YTexIndex, 0);
services->setPixelShaderConstant("YTex", (float*) tids, 1 );
u8* pdata = (u8*) yTex->lock();
//memcpy( pdata, s_Bink->FrameBuffers->Frames[s_Bink->FrameBuffers->FrameNum].YPlane.Buffer,tsize);
yTex->unlock();
//glBindTexture(GL_TEXTURE_2D, s_Textures[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, s_TextureWidth, s_TextureHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, s_Bink->FrameBuffers->Frames[s_Bink->FrameBuffers->FrameNum].YPlane.Buffer);
glActiveTextureARB(GL_TEXTURE1_ARB);
//glUniform1iARB(s_cRTexIndex, 1);
services->setPixelShaderConstant("cRTex", (float*) tids + 1, 1 );
//glBindTexture(GL_TEXTURE_2D, s_Textures[1]);
//glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, s_TextureWidth/2, s_TextureHeight/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, s_Bink->FrameBuffers->Frames[s_Bink->FrameBuffers->FrameNum].cRPlane.Buffer);
pdata = (u8*)cRTex->lock();
//memcpy( pdata, s_Bink->FrameBuffers->Frames[s_Bink->FrameBuffers->FrameNum].cRPlane.Buffer,tsize / 4);
cRTex->unlock();
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, s_TextureWidth/2, s_TextureHeight/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, s_Bink->FrameBuffers->Frames[s_Bink->FrameBuffers->FrameNum].cRPlane.Buffer);
glActiveTextureARB(GL_TEXTURE2_ARB);
//glUniform1iARB(s_cBTexIndex, 2);
services->setPixelShaderConstant("cBTex", (float*) tids + 2, 1 );
//glBindTexture(GL_TEXTURE_2D, s_Textures[2]);
//glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, s_TextureWidth/2, s_TextureHeight/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, s_Bink->FrameBuffers->Frames[s_Bink->FrameBuffers->FrameNum].cBPlane.Buffer);
pdata = (u8*)cBTex->lock();
//memcpy( pdata, s_Bink->FrameBuffers->Frames[s_Bink->FrameBuffers->FrameNum].cRPlane.Buffer,tsize/4);
cBTex->unlock();
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, s_TextureWidth/2, s_TextureHeight/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, s_Bink->FrameBuffers->Frames[s_Bink->FrameBuffers->FrameNum].cBPlane.Buffer);
if (s_HasAlpha)
{
glActiveTextureARB(GL_TEXTURE3_ARB);
//glUniform1iARB(s_ATexIndex, 3);
services->setPixelShaderConstant("ATex", (float*) tids + 2, 1 );
//glBindTexture(GL_TEXTURE_2D, s_Textures[3]);
//glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, s_TextureWidth, s_TextureHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, s_Bink->FrameBuffers->Frames[s_Bink->FrameBuffers->FrameNum].APlane.Buffer);
pdata = (u8*)ATex->lock();
//memcpy( pdata, s_Bink->FrameBuffers->Frames[s_Bink->FrameBuffers->FrameNum].APlane.Buffer,tsize);
ATex->unlock();
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, s_TextureWidth, s_TextureHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, s_Bink->FrameBuffers->Frames[s_Bink->FrameBuffers->FrameNum].APlane.Buffer);
}
}
BinkNextFrame(s_Bink);
}
else
{
Sleep( 10 ); // 1000
}
}
class BinkShader : public video::IShaderConstantSetCallBack
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices* services,
s32 userData)
{
RenderBinkVid( services );
}
};
Code: Select all
BinkShader * pbs = new BinkShader();
s32 bikMat = gpu->addHighLevelShaderMaterialFromFiles(
bikvsname, "vertexMain", video::EVST_VS_1_1,
bikpsname, "pixelMain", video::EPST_PS_1_1,
pbs, video::EMT_SOLID );
video::ITexture * prt1 = driver->addRenderTargetTexture(core::dimension2d<u32>(s_Bink->Width, s_Bink->Height), "rt1", video::ECF_A8R8G8B8);
pblt = driver->addTexture( core::dimension2d<u32>( s_Bink->Width, s_Bink->Height) , "blt", irr::video::ECF_A8R8G8B8); //irr::video::ECF_R8G8B8);
yTex = driver->addTexture( core::dimension2d<u32>( s_Bink->Width/4, s_Bink->Height) , "YTex", irr::video::ECF_A8R8G8B8); //irr::video::ECF_R8G8B8);
cRTex = driver->addTexture( core::dimension2d<u32>( s_Bink->Width/8, s_Bink->Height) , "cRTex", irr::video::ECF_A8R8G8B8); //irr::video::ECF_R8G8B8);
cBTex = driver->addTexture( core::dimension2d<u32>( s_Bink->Width/8, s_Bink->Height) , "cBTex", irr::video::ECF_A8R8G8B8); //irr::video::ECF_R8G8B8);
ATex = driver->addTexture( core::dimension2d<u32>( s_Bink->Width/4, s_Bink->Height) , "ATex", irr::video::ECF_A8R8G8B8); //irr::video::ECF_R8G8B8);
Q1 ) Use standard texture or rendertexture or does it matter ?
Q2) Faster way to set the active texture than Lock()/unlock() ? COpenGLDriver HAS a non-vritual method to setActiveTexture() but it's NOT exposed by the base.
Q3) Use irrlicht ITextures or just leave those 4 allocated by OpenGL?
Q4) Why don't services have a getpixelshaderconstant() so we can minimize the number of loop checks - this could get expensive when there's LOTs of textures?
Your thoughts and feedback are appreciated