native s3d implementation

This commit is contained in:
Bryan Conrad
2014-02-23 11:17:21 -08:00
parent c7830bea6a
commit 5eb972ac5e
16 changed files with 711 additions and 21 deletions

2
.gitignore vendored
View File

@@ -13,3 +13,5 @@ project/vc*.pdb
project/winrt/shaders/
*.userprefs
*.swp
.idea/
*.iml

View File

@@ -170,6 +170,7 @@
<file name="src/platform/android/AndroidFrame.cpp"/>
<file name="src/platform/android/JNI.cpp"/>
<file name="src/platform/android/System.cpp"/>
<file name="src/platform/android/AndroidS3D.cpp"/>
<file name="src/sound/openal/OpenALSound.cpp" if="openal"/>
<compilerflag value="-DAL_LIBTYPE_STATIC" if="openal"/>
@@ -331,6 +332,8 @@
<file name="src/renderer/software/SolidRender.cpp"/>
<file name="src/renderer/software/TileRenderer.cpp"/>
<file name="src/renderer/software/TriangleRender.cpp"/>
<file name="src/common/empty/S3D.cpp" unless="android"/>
</files>
<files id="opengl">
@@ -358,6 +361,7 @@
<file name="src/renderer/opengl/OpenGLInit.cpp"/>
<file name="src/renderer/opengl/OpenGLContext.cpp"/>
<!-- <file name="src/renderer/opengl/OpenGL2Context.cpp"/> -->
<file name="src/renderer/opengl/OpenGLS3D.cpp"/>
<file name="src/renderer/opengl/OpenGLTexture.cpp"/>
<file name="src/renderer/opengl/OpenGLProgram.cpp"/>
<file name="src/renderer/opengl/OpenGLShaders.cpp"/>

View File

@@ -165,6 +165,8 @@ public:
void setX(double inValue);
double getY();
void setY(double inValue);
double getZ();
void setZ(double inValue);
virtual double getHeight();
virtual void setHeight(double inValue);
virtual double getWidth();
@@ -314,6 +316,7 @@ protected:
// Decomp
double x;
double y;
double z;
double scaleX;
double scaleY;
double rotation;
@@ -447,6 +450,8 @@ public:
Matrix GetFullMatrix(bool inStageScaling);
bool FinishEditOnEnter();
void setAutoS3D(bool enabled) { autos3d = enabled; }
bool getAutoS3D() const { return autos3d; }
void setFocusRect(bool inVal) { focusRect = inVal; }
bool getFocusRect() const { return focusRect; }
UserPoint getMousePos() const { return mLastMousePos; }
@@ -478,6 +483,7 @@ protected:
EventHandler mHandler;
void *mHandlerData;
bool focusRect;
bool autos3d;
UserPoint mLastMousePos;
StageScaleMode scaleMode;
StageAlign align;

View File

@@ -11,7 +11,7 @@ class Matrix
public:
Matrix(double inSX=1,double inSY=1, double inTX=0, double inTY=0) :
m00(inSX), m01(0), mtx(inTX),
m10(0), m11(inSY), mty(inTY)
m10(0), m11(inSY), mty(inTY), mtz(0)
{
}
@@ -79,6 +79,7 @@ public:
double m00, m01, mtx;
double m10, m11, mty;
double mtz;
};

View File

@@ -36,6 +36,9 @@ namespace lime {
virtual void SetWindowSize (int inWidth, int inHeight) = 0;
virtual int Width () const = 0;
virtual void EndS3DRender () { };
virtual void SetS3DEye (int eye) { };
};

View File

@@ -0,0 +1,21 @@
#ifndef LIME_S3D_H
#define LIME_S3D_H
namespace lime {
enum S3DOrientation {
S3D_ORIENTATION_VERTICAL,
S3D_ORIENTATION_HORIZONTAL
};
namespace S3D {
void SetEnabled (bool enabled);
void SetOrientation (S3DOrientation orientation);
bool GetEnabled ();
bool IsSupported ();
} // end namespace S3D
} // end namespace lime
#endif

View File

@@ -0,0 +1,14 @@
#ifndef LIME_S3D_EYE_H
#define LIME_S3D_EYE_H
namespace lime {
enum S3DEye {
EYE_MIDDLE,
EYE_LEFT,
EYE_RIGHT
};
}
#endif

View File

@@ -5,6 +5,8 @@
#include <LimeThread.h>
#include "renderer/opengl/OGL.h"
#include "renderer/common/HardwareContext.h"
#include "renderer/opengl/OpenGLProgram.h"
#include "renderer/opengl/OpenGLS3D.h"
namespace lime {
@@ -36,6 +38,9 @@ namespace lime {
void SetViewport (const Rect &inRect);
void SetWindowSize (int inWidth, int inHeight);
void EndS3DRender ();
void SetS3DEye (int eye);
int Height () const { return mHeight; }
int Width () const { return mWidth; }
@@ -63,6 +68,7 @@ namespace lime {
QuickVec<GLuint> mZombieTextures;
QuickVec<GLuint> mZombieVbos;
OpenGLS3D mS3D;
};

View File

@@ -0,0 +1,46 @@
#ifndef LIME_RENDERER_OPENGL_S3D_H
#define LIME_RENDERER_OPENGL_S3D_H
#include "renderer/opengl/OGL.h"
#include "renderer/opengl/OpenGLProgram.h"
namespace lime {
class OpenGLS3D {
public:
OpenGLS3D ();
~OpenGLS3D ();
void Init ();
void EndS3DRender (int inWidth, int inHeight, const Trans4x4 &inTrans);
void SetS3DEye (int eye);
void Resize (int inWidth, int inHeight);
void FocusEye (Trans4x4 &outTrans);
double GetEyeOffset ();
double mFocalLength;
double mEyeSeparation;
private:
int mWidth;
int mHeight;
int mCurrentEye;
OpenGLProgram *mS3DProgram;
GLuint mFramebuffer;
GLuint mRenderbuffer;
GLuint mLeftEyeTexture;
GLuint mRightEyeTexture;
GLuint mEyeMaskTexture;
GLint mLeftImageUniform;
GLint mRightImageUniform;
GLint mMaskImageUniform;
GLint mPixelSizeUniform;
GLint mScreenUniform;
GLuint mS3DVertexBuffer;
GLuint mS3DTextureBuffer;
};
}; // namespace lime
#endif

View File

@@ -3,6 +3,8 @@
#include "renderer/common/SimpleSurface.h"
#include "renderer/common/AutoSurfaceRender.h"
#include "renderer/common/BitmapCache.h"
#include "renderer/common/S3D.h"
#include "renderer/common/S3DEye.h"
#include <math.h>
#ifndef M_PI
@@ -29,6 +31,7 @@ DisplayObject::DisplayObject(bool inInitRef) : Object(inInitRef)
mGfx = 0;
mDirtyFlags = 0;
x = y = 0;
z = 0.1;
scaleX = scaleY = 1.0;
rotation = 0;
visible = true;
@@ -334,6 +337,7 @@ Matrix &DisplayObject::GetLocalMatrix()
mLocalMatrix.m11 = c*scaleY;
mLocalMatrix.mtx = x;
mLocalMatrix.mty = y;
mLocalMatrix.mtz = z;
}
return mLocalMatrix;
}
@@ -354,6 +358,7 @@ void DisplayObject::UpdateDecomp()
mDirtyFlags ^= dirtDecomp;
x = mLocalMatrix.mtx;
y = mLocalMatrix.mty;
z = mLocalMatrix.mtz;
scaleX = sqrt( mLocalMatrix.m00*mLocalMatrix.m00 +
mLocalMatrix.m10*mLocalMatrix.m10 );
scaleY = sqrt( mLocalMatrix.m01*mLocalMatrix.m01 +
@@ -537,6 +542,23 @@ void DisplayObject::setScaleY(double inValue)
}
}
double DisplayObject::getZ()
{
UpdateDecomp();
return z;
}
void DisplayObject::setZ(double inValue)
{
UpdateDecomp();
if (z!=inValue)
{
mDirtyFlags |= dirtLocalMatrix;
z = inValue;
DirtyCache(true);
}
}
void DisplayObject::setScale9Grid(const DRect &inRect)
{
scale9Grid = inRect;
@@ -1526,6 +1548,7 @@ Stage::Stage(bool inInitRef) : DisplayObjectContainer(inInitRef)
mNextWake = 0.0;
displayState = sdsNormal;
align = saTopLeft;
autos3d = true;
#if defined(IPHONE) || defined(ANDROID) || defined(WEBOS) || defined(TIZEN)
quality = sqLow;
@@ -1673,8 +1696,8 @@ void Stage::HandleEvent(Event &inEvent)
{
UserPoint pixels(inEvent.x,inEvent.y);
hit_obj = HitTest(pixels);
//if (inEvent.type!=etTouchMove)
//ELOG(" type=%d %d,%d obj=%p (%S)", inEvent.type, inEvent.x, inEvent.y, hit_obj, hit_obj?hit_obj->name.c_str():L"(none)");
// if (inEvent.type!=etTouchMove)
// ELOG(" type=%d %d,%d obj=%p (%S)", inEvent.type, inEvent.x, inEvent.y, hit_obj, hit_obj?hit_obj->name.c_str():L"(none)");
SimpleButton *but = hit_obj ? dynamic_cast<SimpleButton *>(hit_obj) : 0;
inEvent.id = hit_obj ? hit_obj->id : id;
@@ -1918,6 +1941,20 @@ void Stage::RenderStage()
{
ColorTransform::TidyCache();
AutoStageRender render(this,opaqueBackground);
S3DEye start = EYE_MIDDLE;
S3DEye end = EYE_MIDDLE;
if(autos3d && S3D::GetEnabled()) {
start = EYE_LEFT;
end = EYE_RIGHT;
}
for(int eye = start; eye <= end; eye++) {
render.Target().mHardware->SetS3DEye(eye);
if (render.Target().IsHardware())
render.Target().mHardware->SetQuality(quality);
@@ -1934,6 +1971,12 @@ void Stage::RenderStage()
state.mPhase = rpRender;
Render(render.Target(),state);
}
if(autos3d && S3D::GetEnabled()) {
render.Target().mHardware->EndS3DRender();
}
// Clear alpha masks
}

View File

@@ -1344,11 +1344,12 @@ value lime_stage_set_focus(value inStage,value inObject,value inDirection)
DEFINE_PRIM(lime_stage_set_focus,3);
DO_STAGE_PROP(focus_rect,FocusRect,alloc_bool,val_bool)
DO_STAGE_PROP(scale_mode,ScaleMode,alloc_int,val_int)
DO_STAGE_PROP(autos3d,AutoS3D,alloc_bool,val_bool)
DO_STAGE_PROP(align,Align,alloc_int,val_int)
DO_STAGE_PROP(quality,Quality,alloc_int,val_int)
DO_STAGE_PROP(display_state,DisplayState,alloc_int,val_int)
DO_STAGE_PROP(multitouch_active,MultitouchActive,alloc_bool,val_bool)
DO_STAGE_PROP(scale_mode,ScaleMode,alloc_int,val_int)
DO_PROP_READ(Stage,stage,stage_width,StageWidth,alloc_float);
DO_PROP_READ(Stage,stage,stage_height,StageHeight,alloc_float);
DO_PROP_READ(Stage,stage,dpi_scale,DPIScale,alloc_float);
@@ -1915,6 +1916,7 @@ DEFINE_PRIM(lime_display_object_dismiss_soft_keyboard,1);
DO_DISPLAY_PROP(x,X,alloc_float,val_number)
DO_DISPLAY_PROP(y,Y,alloc_float,val_number)
DO_DISPLAY_PROP(z,Z,alloc_float,val_number)
DO_DISPLAY_PROP(scale_x,ScaleX,alloc_float,val_number)
DO_DISPLAY_PROP(scale_y,ScaleY,alloc_float,val_number)
DO_DISPLAY_PROP(rotation,Rotation,alloc_float,val_number)
@@ -3075,6 +3077,11 @@ TEXT_PROP(max_chars,MaxChars,alloc_int,val_int);
TEXT_PROP_GET_IDX(line_text,LineText,alloc_wstring);
TEXT_PROP_GET_IDX(line_offset,LineOffset,alloc_int);
value lime_bitmap_data_set_alpha_mode(value a, value b)
{
return alloc_null();
}
DEFINE_PRIM(lime_bitmap_data_set_alpha_mode,2);
value lime_bitmap_data_create(value* arg, int nargs)
{

View File

@@ -80,6 +80,8 @@ Matrix Matrix::Mult(const Matrix &inRHS) const
t.m11 = m10*inRHS.m01 + m11*inRHS.m11;
t.mty = m10*inRHS.mtx + m11*inRHS.mty + mty;
t.mtz = inRHS.mtz + mtz;
return t;
}

View File

@@ -0,0 +1,34 @@
#include <renderer/common/S3D.h>
#include <hx/CFFI.h>
#include <Object.h>
namespace lime {
namespace S3D {
void SetEnabled (bool enabled) { }
void SetOrientation (S3DOrientation orientation) { }
bool GetEnabled () { return false; }
bool IsSupported () { return false; }
value lime_get_s3d_enabled () {
return alloc_bool (S3D::GetEnabled ());
}
DEFINE_PRIM (lime_get_s3d_enabled, 0);
value lime_set_s3d_enabled (value enabled) {
S3D::SetEnabled (val_bool (enabled));
return alloc_null ();
}
DEFINE_PRIM (lime_set_s3d_enabled, 1);
value lime_get_s3d_supported () {
return alloc_bool (S3D::IsSupported ());
}
DEFINE_PRIM (lime_get_s3d_supported, 0);
} // end namespace S3D
} // end namespace lime

View File

@@ -0,0 +1,110 @@
#include <hx/CFFI.h>
#include <renderer/common/S3D.h>
#include <Object.h>
#include <fstream>
namespace lime {
namespace S3D {
const char* MI3D_TN_CTRL_FILE = "/dev/mi3d_tn_ctrl";
bool gS3DEnabled = false;
S3DOrientation gS3DOrientation = S3D_ORIENTATION_VERTICAL;
const int MI3D_GET_TN_STATUS = 128;
const int MI3D_SET_HORIZONTAL_TN_ON = 64;
const int MI3D_SET_TN_OFF = 16;
const int MI3D_SET_VERTICAL_TN_ON = 32;
void Enact () {
unsigned char value = MI3D_SET_TN_OFF;
if (gS3DEnabled) {
if (gS3DOrientation == S3D_ORIENTATION_VERTICAL) {
value = MI3D_SET_VERTICAL_TN_ON;
} else {
value = MI3D_SET_HORIZONTAL_TN_ON;
}
}
std::fstream file;
file.open (MI3D_TN_CTRL_FILE);
if (file.is_open ()) {
file << value;
file.close ();
}
}
void SetEnabled (bool enabled) {
gS3DEnabled = enabled;
Enact ();
}
void SetOrientation (S3DOrientation orientation) {
gS3DOrientation = orientation;
Enact ();
}
bool GetEnabled () {
return gS3DEnabled;
}
bool IsSupported () {
std::fstream file;
file.open (MI3D_TN_CTRL_FILE, std::ios_base::in);
bool result = file.is_open ();
file.close ();
return result;
}
value lime_get_s3d_enabled () {
return alloc_bool (S3D::GetEnabled ());
}
DEFINE_PRIM (lime_get_s3d_enabled, 0);
value lime_set_s3d_enabled (value enabled) {
S3D::SetEnabled (val_bool (enabled));
return alloc_null ();
}
DEFINE_PRIM (lime_set_s3d_enabled, 1);
value lime_get_s3d_supported () {
return alloc_bool (S3D::IsSupported ());
}
DEFINE_PRIM (lime_get_s3d_supported, 0);
} // end namespace S3D
} // end namespace lime

View File

@@ -1,4 +1,6 @@
#include "renderer/opengl/OpenGLContext.h"
#include "renderer/common/S3D.h"
#include "renderer/common/S3DEye.h"
int sgDrawCount = 0;
@@ -55,6 +57,8 @@ namespace lime {
e.mTexOffset = sizeof (float) * 2;
e.mStride = sizeof (float) * 4;
mS3D.Init ();
}
@@ -186,16 +190,25 @@ namespace lime {
void OpenGLContext::CombineModelView (const Matrix &inModelView) {
float eyeOffset = mS3D.GetEyeOffset ();
mTrans[0][0] = inModelView.m00 * mScaleX;
mTrans[0][1] = inModelView.m01 * mScaleX;
mTrans[0][2] = 0;
mTrans[0][3] = inModelView.mtx * mScaleX + mOffsetX;
mTrans[0][3] = (inModelView.mtx + eyeOffset) * mScaleX + mOffsetX;
mTrans[1][0] = inModelView.m10 * mScaleY;
mTrans[1][1] = inModelView.m11 * mScaleY;
mTrans[1][2] = 0;
mTrans[1][3] = inModelView.mty * mScaleY + mOffsetY;
mTrans[2][0] = 0;
mTrans[2][1] = 0;
mTrans[2][2] = -1;
mTrans[2][3] = inModelView.mtz;
mS3D.FocusEye (mTrans);
}
@@ -687,7 +700,27 @@ namespace lime {
//__android_log_print(ANDROID_LOG_ERROR, "Lime", "SetWindowSize %d %d", inWidth, inHeight);
#endif
if (mWidth > mHeight) {
S3D::SetOrientation (S3D_ORIENTATION_VERTICAL);
} else {
S3D::SetOrientation (S3D_ORIENTATION_HORIZONTAL);
}
mS3D.Resize (inWidth, inHeight);
}
void OpenGLContext::EndS3DRender() {
setOrtho (0, mWidth, 0, mHeight);
mS3D.EndS3DRender (mWidth, mHeight, mTrans);
}
void OpenGLContext::SetS3DEye(int eye) {
mS3D.SetS3DEye (eye);
}
}

View File

@@ -0,0 +1,358 @@
#include "renderer/opengl/OpenGLS3D.h"
#include "renderer/opengl/OpenGLContext.h"
#include "renderer/common/S3D.h"
#include "renderer/common/S3DEye.h"
// #include "common/Display.h"
namespace lime {
OpenGLS3D::OpenGLS3D () {
mFocalLength = 0.5;
mEyeSeparation = 0.01;
mCurrentEye = EYE_MIDDLE;
}
OpenGLS3D::~OpenGLS3D () {
glDeleteRenderbuffers (1, &mRenderbuffer);
glDeleteFramebuffers (1, &mFramebuffer);
glDeleteTextures (1, &mLeftEyeTexture);
glDeleteTextures (1, &mRightEyeTexture);
glDeleteTextures (1, &mEyeMaskTexture);
glDeleteBuffers (1, &mS3DVertexBuffer);
glDeleteBuffers (1, &mS3DTextureBuffer);
delete mS3DProgram;
}
void OpenGLS3D::Init () {
// TODO: renderbuffer is only needed when using depth buffer
glGenRenderbuffers (1, &mRenderbuffer);
glGenFramebuffers (1, &mFramebuffer);
glGenBuffers (1, &mS3DVertexBuffer);
glGenBuffers (1, &mS3DTextureBuffer);
mCurrentEye = EYE_MIDDLE;
mLeftEyeTexture = mRightEyeTexture = mEyeMaskTexture = 0;
mS3DProgram = new OpenGLProgram (
/* vertex */
"attribute vec3 aVertex;\n"
"attribute vec2 aTexCoord;\n"
"varying vec2 vTexCoord;\n"
"uniform mat4 uTransform;"
"\n"
"void main (void) {\n"
" vTexCoord = aTexCoord;\n"
" gl_Position = vec4 (aVertex, 1.0) * uTransform;\n"
"}\n"
,
/* fragment */
#if defined (LIME_GLES)
// TODO: highp precision is required for screens above a certain
// dimension, however, GLES doesn't guarantee highp support in fragment
// shaders
"precision highp float;\n"
"precision highp sampler2D;\n"
#endif
"varying vec2 vTexCoord;\n"
"uniform sampler2D uLeft;\n"
"uniform sampler2D uRight;\n"
"uniform sampler2D uMask;\n"
"\n"
"void main (void)\n"
"{\n"
" float parity = mod (gl_FragCoord.x, 2.0);\n"
" vec4 left = texture2D (uLeft, vTexCoord).rgba;\n"
" vec4 right = texture2D (uRight, vTexCoord).rgba;\n"
" float mask = texture2D (uMask, floor (gl_FragCoord.xy) / vec2 (2.0, 1.0)).x;\n"
" gl_FragColor = mix (left, right, mask);\n"
"}\n"
);
mLeftImageUniform = glGetUniformLocation (mS3DProgram->mProgramId, "uLeft");
mRightImageUniform = glGetUniformLocation (mS3DProgram->mProgramId, "uRight");
mMaskImageUniform = glGetUniformLocation (mS3DProgram->mProgramId, "uMask");
mPixelSizeUniform = glGetUniformLocation (mS3DProgram->mProgramId, "pixelSize");
}
void OpenGLS3D::SetS3DEye (int eye) {
if (eye == EYE_MIDDLE) {
return;
}
mCurrentEye = eye;
GLint texture = mRightEyeTexture;
if (eye == EYE_LEFT) {
texture = mLeftEyeTexture;
}
glActiveTexture (GL_TEXTURE0);
// TODO: no need to bind 0 texture here, right?
glBindTexture (GL_TEXTURE_2D, 0);
glBindFramebuffer (GL_FRAMEBUFFER, mFramebuffer);
glBindRenderbuffer (GL_RENDERBUFFER, mRenderbuffer);
glBindTexture (GL_TEXTURE_2D, texture);
glFramebufferTexture2D (
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, texture, 0);
glClearColor (0, 0, 0, 1.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void OpenGLS3D::EndS3DRender (int inWidth, int inHeight, const Trans4x4 &inTrans) {
mCurrentEye = EYE_MIDDLE;
const GLfloat verts[] =
{
inWidth, inHeight, 0,
0, inHeight, 0,
inWidth, 0, 0,
0, 0, 0
};
static const GLfloat textureCoords[] =
{
1, 1,
0, 1,
1, 0,
0, 0
};
glBindRenderbuffer (GL_RENDERBUFFER, 0);
glBindFramebuffer (GL_FRAMEBUFFER, 0);
// use the multiplexing shader
mS3DProgram->bind ();
glClearColor (0, 0, 0, 1.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnableVertexAttribArray (mS3DProgram->vertexSlot);
glEnableVertexAttribArray (mS3DProgram->textureSlot);
glBindBuffer (GL_ARRAY_BUFFER, mS3DVertexBuffer);
glBufferData (GL_ARRAY_BUFFER, sizeof (GLfloat) * 12, verts, GL_STATIC_DRAW);
glVertexAttribPointer (mS3DProgram->vertexSlot, 3, GL_FLOAT, false, 0, 0);
glBindBuffer (GL_ARRAY_BUFFER, mS3DTextureBuffer);
glBufferData (GL_ARRAY_BUFFER, sizeof (GLfloat) * 8, textureCoords, GL_STATIC_DRAW);
glVertexAttribPointer (mS3DProgram->textureSlot, 2, GL_FLOAT, false, 0, 0);
// bind left eye texture
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, mLeftEyeTexture);
glUniform1i (mLeftImageUniform, 0);
// bind right eye texture
glActiveTexture (GL_TEXTURE1);
glBindTexture (GL_TEXTURE_2D, mRightEyeTexture);
glUniform1i (mRightImageUniform, 1);
// bind eye mask
glActiveTexture (GL_TEXTURE2);
glBindTexture (GL_TEXTURE_2D, mEyeMaskTexture);
glUniform1i (mMaskImageUniform, 2);
// supply our matrices and screen info
glUniformMatrix4fv (mS3DProgram->mTransformSlot, 1, false, (const GLfloat*) inTrans);
// here's where the magic happens
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
// glDisable (GL_TEXTURE_2D);
// clean up
glBindBuffer (GL_ARRAY_BUFFER, 0);
glDisableVertexAttribArray (mS3DProgram->vertexSlot);
glDisableVertexAttribArray (mS3DProgram->textureSlot);
glUseProgram (0);
glBindRenderbuffer (GL_RENDERBUFFER, 0);
glBindFramebuffer (GL_FRAMEBUFFER, 0);
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, 0);
glActiveTexture (GL_TEXTURE1);
glBindTexture (GL_TEXTURE_2D, 0);
glActiveTexture (GL_TEXTURE2);
glBindTexture (GL_TEXTURE_2D, 0);
}
void OpenGLS3D::Resize (int inWidth, int inHeight) {
if (mLeftEyeTexture != 0) {
glDeleteTextures (1, &mLeftEyeTexture);
glDeleteTextures (1, &mRightEyeTexture);
glDeleteTextures (1, &mEyeMaskTexture);
}
int texWidth = inWidth; // UpToPower2 (inWidth);
int texHeight = inHeight; // UpToPower2 (inHeight);
glGenTextures (1, &mLeftEyeTexture);
glBindTexture (GL_TEXTURE_2D, mLeftEyeTexture);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture (GL_TEXTURE_2D, 0);
glGenTextures (1, &mRightEyeTexture);
glBindTexture (GL_TEXTURE_2D, mRightEyeTexture);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture (GL_TEXTURE_2D, 0);
GLubyte maskData[] = {
0, 0xFF,
0, 0xFF
};
glGenTextures (1, &mEyeMaskTexture);
glBindTexture (GL_TEXTURE_2D, mEyeMaskTexture);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, maskData);
glBindTexture (GL_TEXTURE_2D, 0);
// create depth buffer
glBindRenderbuffer (GL_RENDERBUFFER, mRenderbuffer);
glBindFramebuffer (GL_FRAMEBUFFER, mFramebuffer);
glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, inWidth, inHeight);
glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mRenderbuffer);
glBindRenderbuffer (GL_RENDERBUFFER, 0);
glBindFramebuffer (GL_FRAMEBUFFER, 0);
}
void OpenGLS3D::FocusEye (Trans4x4 &outTrans) {
if (mCurrentEye != EYE_MIDDLE) {
float offset = GetEyeOffset ();
float theta = asin (offset/mFocalLength);
float m = sin (theta);
float n = cos (theta);
float a = outTrans[0][0];
float b = outTrans[0][1];
float c = outTrans[1][0];
float d = outTrans[1][1];
float tx = outTrans[0][3];
float ty = outTrans[1][3];
float tz = outTrans[2][3];
outTrans[0][0] = (a*n);
outTrans[0][1] = (b*n);
outTrans[0][2] = m;
outTrans[0][3] = (n*tx + m*tz);
outTrans[1][0] = c;
outTrans[1][1] = d;
outTrans[1][2] = 0;
outTrans[1][3] = ty;
outTrans[2][0] = -a*m;
outTrans[2][1] = -b*m;
outTrans[2][2] = -n;
outTrans[2][3] = -(n*tz-m*tx);
}
}
double OpenGLS3D::GetEyeOffset () {
if (mCurrentEye == EYE_MIDDLE) {
return 0;
} else if (mCurrentEye == EYE_LEFT) {
return -1 * mEyeSeparation;
}
return mEyeSeparation;
}
extern HardwareContext *gDirectRenderContext;
value lime_gl_s3d_set_focal_length (value length)
{
OpenGLContext* ctx = dynamic_cast<OpenGLContext*> (HardwareContext::current);
if (ctx) {
ctx->mS3D.mFocalLength = val_float (length);
}
}
DEFINE_PRIM (lime_gl_s3d_set_focal_length,1);
value lime_gl_s3d_get_focal_length ()
{
OpenGLContext* ctx = dynamic_cast<OpenGLContext*> (HardwareContext::current);
if (ctx) {
return alloc_float (ctx->mS3D.mFocalLength);
}
return alloc_null ();
}
DEFINE_PRIM (lime_gl_s3d_get_focal_length,0);
value lime_gl_s3d_set_eye_separation (value separation)
{
OpenGLContext* ctx = dynamic_cast<OpenGLContext*> (HardwareContext::current);
if (ctx) {
ctx->mS3D.mEyeSeparation = val_float (separation);
}
}
DEFINE_PRIM (lime_gl_s3d_set_eye_separation,1);
value lime_gl_s3d_get_eye_separation ()
{
OpenGLContext* ctx = dynamic_cast<OpenGLContext*> (HardwareContext::current);
if (ctx) {
return alloc_float (ctx->mS3D.mEyeSeparation);
}
return alloc_null ();
}
DEFINE_PRIM (lime_gl_s3d_get_eye_separation,0);
};