diff --git a/core/src/gcanvas/GCanvas2dContext.cpp b/core/src/gcanvas/GCanvas2dContext.cpp index 6855b42f..4ad7a213 100644 --- a/core/src/gcanvas/GCanvas2dContext.cpp +++ b/core/src/gcanvas/GCanvas2dContext.cpp @@ -1821,6 +1821,52 @@ void GCanvasContext::SetFillStyle(const char *str) GColorRGBA color = StrValueToColorRGBA(str); SetFillStyle(color); + // mock(); +} + +void GCanvasContext::mock() +{ + glClearColor(1.0, 1.0, 1.0, 1.0); + glViewport(0, 0, mWidth, mHeight); + glClear(GL_COLOR_BUFFER_BIT); + static const GLfloat g_vertex_buffer_data[] = { + -1.0f, + -1.0f, + 0.0f, + 1.0f, + -1.0f, + 0.0f, + 0.0f, + 1.0f, + 0.0f, + }; + GLuint vertexbuffer; + // Generate 1 buffer, put the resulting identifier in vertexbuffer + glGenBuffers(1, &vertexbuffer); + + // The following commands will talk about our 'vertexbuffer' buffer + glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); + + // Give our vertices to OpenGL. + glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW); + + // 1rst attribute buffer : vertices + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); + glVertexAttribPointer( + 0, // attribute 0. No particular reason for 0, but must match the layout in the shader. + 3, // size + GL_FLOAT, // type + GL_FALSE, // normalized? + 0, // stride + (void *)0 // array buffer offset + ); + // Draw the triangle ! + + glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle + + // glDisableVertexAttribArray(0); + // glFlush(); } void GCanvasContext::SetFillStyle(GColorRGBA c) diff --git a/core/src/gcanvas/GCanvas2dContext.h b/core/src/gcanvas/GCanvas2dContext.h index 70db9425..587384d9 100644 --- a/core/src/gcanvas/GCanvas2dContext.h +++ b/core/src/gcanvas/GCanvas2dContext.h @@ -93,7 +93,7 @@ class GCanvasContext { API_EXPORT bool InitializeGLEnvironment(); bool InitializeGLShader(); void ResetStateStack(); - + void mock(); void BindVertexBuffer(); void ClearGeometryDataBuffers(); API_EXPORT void SendVertexBufferToGPU(const GLenum geometry_type = GL_TRIANGLES); diff --git a/node/CMakeLists.txt b/node/CMakeLists.txt index 21e7f102..eda6dbbc 100644 --- a/node/CMakeLists.txt +++ b/node/CMakeLists.txt @@ -16,15 +16,15 @@ project(canvas) # CMake JS include_directories(${CMAKE_JS_INC}) -include_directories("./util") +include_directories("./binding/util") include_directories("./third_party") include_directories("./third_party/font/freetype2/") -include_directories("./renderContext/") +include_directories("./binding/renderContext/") include_directories("./image/") include_directories("${CORE_DIR}") include_directories("${CORE_DIR}src/") -include_directories("${CORE_DIR}src") +include_directories("${CORE_DIR}src/webgl/") include_directories("${CORE_DIR}src/gcanvas") include_directories("${CORE_DIR}src/gcanvas/GL") include_directories("${CORE_DIR}src/support") @@ -35,15 +35,24 @@ set(SOURCE_FILES ./binding/Export.cc ./binding/Canvas.cc ./binding/CanvasRenderingContext2D.cc + ./binding/CanvasRenderingContextWebGL.cc ./binding/CanvasGradient.cc ./binding/ImageData.cc ./binding/TextMetrics.cc ./binding/Image.cc ./binding/ImageWorker.cc ./binding/CanvasPattern.cc - ./renderContext/GRenderContext.cc + ./binding/webgl/WebGLShader.cc + ./binding/webgl/WebGLBuffer.cc + ./binding/webgl/WebGLProgram.cc + ./binding/webgl/WebGLTexture.cc + ./binding/webgl/WebGLFrameBuffer.cc + ./binding/webgl/WebGLRenderBuffer.cc + ./binding/webgl/WebGLActiveInfo.cc + ./binding/webgl/WebGLUniformLocation.cc + ./binding/renderContext/GRenderContext.cc + ./binding/util/NodeBindingUtil.cc ./third_party/lodepng.cc - ./util/NodeBindingUtil.cc ${CORE_DIR}src/GCanvas.cpp ${CORE_DIR}src/GCanvasManager.cpp diff --git a/node/binding/Canvas.cc b/node/binding/Canvas.cc index 8c26fce5..5d8d904f 100644 --- a/node/binding/Canvas.cc +++ b/node/binding/Canvas.cc @@ -20,7 +20,7 @@ namespace NodeBinding checkArgs(info, 2); mWidth = info[0].As().Int32Value(); mHeight = info[1].As().Int32Value(); - mRenderContext = std::make_shared(mWidth, mHeight,2.0); + mRenderContext = std::make_shared(mWidth, mHeight, 2.0); mRenderContext->initRenderEnviroment(); } @@ -82,23 +82,45 @@ namespace NodeBinding std::string type = info[0].As().Utf8Value(); if (type == "2d") { - if (this->context2dRef.IsEmpty()) + if (mContext2dRef.IsEmpty()) { Napi::Object obj = Context2D::NewInstance(env); - this->context2dRef = Napi::ObjectReference::New(obj); Context2D *ctx = Napi::ObjectWrap::Unwrap(obj); - ctx->setRenderContext(this->mRenderContext); + mRenderContext->setType(type); + ctx->setRenderContext(mRenderContext); ctx->setCanvasRef(this); + + //save reference + mContext2dRef = Napi::ObjectReference::New(obj); + return obj; + } + else + { + return mContext2dRef.Value(); + } + } + else if (type == "webgl") + { + if (mContextWebGLRef.IsEmpty()) + { + Napi::Object obj = ContextWebGL::NewInstance(env); + ContextWebGL *ctx = Napi::ObjectWrap::Unwrap(obj); + ctx->setRenderContext(mRenderContext); + mRenderContext->setType(type); + obj.Set("canvas", this->Value()); + + // save reference + mContextWebGLRef = Napi::ObjectReference::New(obj); return obj; } else { - return this->context2dRef.Value(); + return mContextWebGLRef.Value(); } } else { - throwError(info, "only support 2d now"); + throwError(info, "type is invalid \n"); return Napi::Object::New(env); } } @@ -106,11 +128,11 @@ namespace NodeBinding { NodeBinding::checkArgs(info, 1); std::string arg = info[0].As().Utf8Value(); - if (this->mRenderContext) + if (mRenderContext) { - this->mRenderContext->makeCurrent(); - this->mRenderContext->drawFrame(); - this->mRenderContext->render2file(arg.c_str(), PNG_FORAMT); + mRenderContext->makeCurrent(); + mRenderContext->drawFrame(); + mRenderContext->render2file(arg.c_str(), PNG_FORAMT); } return; } @@ -118,11 +140,11 @@ namespace NodeBinding { NodeBinding::checkArgs(info, 1); std::string arg = info[0].As().Utf8Value(); - if (this->mRenderContext) + if (mRenderContext) { - this->mRenderContext->makeCurrent(); - this->mRenderContext->drawFrame(); - this->mRenderContext->render2file(arg.c_str(), JPEG_FORMAT); + mRenderContext->makeCurrent(); + mRenderContext->drawFrame(); + mRenderContext->render2file(arg.c_str(), JPEG_FORMAT); } return; } @@ -130,7 +152,7 @@ namespace NodeBinding { NodeBinding::checkArgs(info, 2); unsigned long size = 0; - Napi::Buffer buffer = this->getJPGBuffer(info, size); + Napi::Buffer buffer = getJPGBuffer(info, size); if (size >= 0) { Napi::Function callback = info[0].As(); @@ -155,7 +177,7 @@ namespace NodeBinding { NodeBinding::checkArgs(info, 2); unsigned long size = 0; - Napi::Buffer buffer = this->getPNGBuffer(info, size); + Napi::Buffer buffer = getPNGBuffer(info, size); if (size >= 0) { Napi::Function callback = info[0].As(); @@ -177,13 +199,13 @@ namespace NodeBinding } Napi::Buffer Canvas::getPNGBuffer(const Napi::CallbackInfo &info, unsigned long &size) { - if (this->mRenderContext) + if (mRenderContext) { - this->mRenderContext->makeCurrent(); - this->mRenderContext->drawFrame(); + mRenderContext->makeCurrent(); + mRenderContext->drawFrame(); } std::vector dataPNGFormat; - int ret = this->mRenderContext->getImagePixelPNG(dataPNGFormat); + int ret = mRenderContext->getImagePixelPNG(dataPNGFormat); if (ret == 0) { size = dataPNGFormat.size(); @@ -196,13 +218,13 @@ namespace NodeBinding } Napi::Buffer Canvas::getJPGBuffer(const Napi::CallbackInfo &info, unsigned long &size) { - if (this->mRenderContext) + if (mRenderContext) { - this->mRenderContext->makeCurrent(); - this->mRenderContext->drawFrame(); + mRenderContext->makeCurrent(); + mRenderContext->drawFrame(); } unsigned char *dataJPGFormat = nullptr; - int ret = this->mRenderContext->getImagePixelJPG(&dataJPGFormat, size); + int ret = mRenderContext->getImagePixelJPG(&dataJPGFormat, size); if (ret == 0) { return Napi::Buffer::Copy(info.Env(), dataJPGFormat, size); @@ -216,14 +238,14 @@ namespace NodeBinding Napi::Buffer Canvas::getRawDataBuffer(const Napi::CallbackInfo &info, unsigned long &size) { - if (this->mDataRaw == nullptr) + if (mDataRaw == nullptr) { - this->mDataRaw = new unsigned char[4 * mWidth * mHeight]; + mDataRaw = new unsigned char[4 * mWidth * mHeight]; } - int ret = this->mRenderContext->readPixelAndSampleFromCurrentCtx(mDataRaw); + int ret = mRenderContext->readPixelAndSampleFromCurrentCtx(mDataRaw); if (ret == 0) { - return Napi::Buffer::Copy(info.Env(), this->mDataRaw, 4 * mWidth * mHeight); + return Napi::Buffer::Copy(info.Env(), mDataRaw, 4 * mWidth * mHeight); } else { @@ -237,7 +259,7 @@ namespace NodeBinding //默认输出png 编码 if (info.Length() == 0) { - return this->getPNGBuffer(info, size); + return getPNGBuffer(info, size); } else { @@ -247,15 +269,15 @@ namespace NodeBinding std::string mimeType = info[0].As().Utf8Value(); if (mimeType == "image/png") { - ret = this->getPNGBuffer(info, size); + ret = getPNGBuffer(info, size); } else if (mimeType == "image/jpeg") { - ret = this->getJPGBuffer(info, size); + ret = getJPGBuffer(info, size); } else if (mimeType == "raw") { - ret = this->getRawDataBuffer(info, size); + ret = getRawDataBuffer(info, size); } } if (size < 0) @@ -270,11 +292,11 @@ namespace NodeBinding } Canvas::~Canvas() { - this->mRenderContext = nullptr; - if (this->mDataRaw != nullptr) + mRenderContext = nullptr; + if (mDataRaw != nullptr) { - free(this->mDataRaw); - this->mDataRaw = nullptr; + free(mDataRaw); + mDataRaw = nullptr; } printf("canvas destroy called \n"); } diff --git a/node/binding/Canvas.h b/node/binding/Canvas.h index 9c6c3a91..214747b0 100644 --- a/node/binding/Canvas.h +++ b/node/binding/Canvas.h @@ -10,6 +10,7 @@ #define CANVAS_H #include "GRenderContext.h" #include "CanvasRenderingContext2D.h" +#include "CanvasRenderingContextWebGL.h" #include "CanvasGradient.h" #include "ImageData.h" #include "CanvasPattern.h" @@ -41,7 +42,9 @@ namespace NodeBinding Napi::Buffer getPNGBuffer(const Napi::CallbackInfo &info, unsigned long &size); Napi::Buffer getJPGBuffer(const Napi::CallbackInfo &info, unsigned long &size); Napi::Buffer getRawDataBuffer(const Napi::CallbackInfo &info, unsigned long &size); - Napi::ObjectReference context2dRef; + + Napi::ObjectReference mContext2dRef; + Napi::ObjectReference mContextWebGLRef; void setWidth(const Napi::CallbackInfo &info, const Napi::Value &value); void setHeight(const Napi::CallbackInfo &info, const Napi::Value &value); diff --git a/node/binding/CanvasRenderingContext2D.cc b/node/binding/CanvasRenderingContext2D.cc index b76affd1..c2426cdd 100644 --- a/node/binding/CanvasRenderingContext2D.cc +++ b/node/binding/CanvasRenderingContext2D.cc @@ -15,6 +15,7 @@ #include "TextMetrics.h" #include +//测量耗时的调试开关 // #define DUMP_RUNNING_TIME 1 #ifdef DUMP_RUNNING_TIME @@ -30,7 +31,7 @@ #define RECORD_TIME_END #endif -#define DEFINE_VOID_METHOD_BEGIN(methodName) \ +#define DEFINE_VOID_METHOD(methodName) \ \ void \ Context2D::methodName(const Napi::CallbackInfo &info) \ @@ -159,7 +160,7 @@ namespace NodeBinding obj.Set("name", Napi::String::New(env, "context2d")); return obj; } - DEFINE_VOID_METHOD_BEGIN(fillRect) + DEFINE_VOID_METHOD(fillRect) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 4); @@ -170,7 +171,7 @@ namespace NodeBinding if (mRenderContext) { - mRenderContext->getCtx()->FillRect(x, y, width, height); + mRenderContext->getCtx2d()->FillRect(x, y, width, height); } RECORD_TIME_END return; @@ -182,7 +183,7 @@ if (mRenderContext) if (value.IsString()) { std::string arg = value.As().Utf8Value(); - mRenderContext->getCtx()->SetFillStyle(arg.c_str()); + mRenderContext->getCtx2d()->SetFillStyle(arg.c_str()); } else if (value.IsObject()) { @@ -207,7 +208,7 @@ if (mRenderContext) offsetArray[i] = colorStop[i].offset; colorArray[i] = colorStop[i].color; } - mRenderContext->getCtx()->SetFillStyleLinearGradient(startArr, endArr, gradient->getCount(), offsetArray, colorArray); + mRenderContext->getCtx2d()->SetFillStyleLinearGradient(startArr, endArr, gradient->getCount(), offsetArray, colorArray); } else if (namePropetry == "radialGradient") { @@ -222,16 +223,16 @@ if (mRenderContext) offsetArray[i] = colorStop[i].offset; colorArray[i] = colorStop[i].color; } - mRenderContext->getCtx()->SetFillStyleRadialGradient(startArr, endArr, gradient->getCount(), offsetArray, colorArray); + mRenderContext->getCtx2d()->SetFillStyleRadialGradient(startArr, endArr, gradient->getCount(), offsetArray, colorArray); } else if (namePropetry == "pattern") { Pattern *pattern = Napi::ObjectWrap::Unwrap(object); - int textureId = mRenderContext->getCtx()->BindImage( + int textureId = mRenderContext->getCtx2d()->BindImage( &pattern->content->getPixels()[0], GL_RGBA, pattern->content->getWidth(), pattern->content->getHeight()); - mRenderContext->getCtx()->SetFillStylePattern( + mRenderContext->getCtx2d()->SetFillStylePattern( textureId, pattern->content->getWidth(), pattern->content->getHeight(), pattern->getRepetition().c_str(), false); @@ -251,13 +252,13 @@ DEFINE_RETURN_VALUE_METHOD(getFillStyle) Napi::Env env = info.Env(); if (mRenderContext) { - return Napi::String::New(env, gcanvas::ColorToString(mRenderContext->getCtx()->FillStyle())); + return Napi::String::New(env, gcanvas::ColorToString(mRenderContext->getCtx2d()->FillStyle())); } RECORD_TIME_END return Napi::String::New(env, ""); } -DEFINE_VOID_METHOD_BEGIN(clearRect) +DEFINE_VOID_METHOD(clearRect) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 4); float x = info[0].As().FloatValue(); @@ -266,12 +267,12 @@ float width = info[2].As().FloatValue(); float height = info[3].As().FloatValue(); if (mRenderContext) { - mRenderContext->getCtx()->ClearRect(x, y, width, height); + mRenderContext->getCtx2d()->ClearRect(x, y, width, height); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(arc) +DEFINE_VOID_METHOD(arc) Napi::Env env = info.Env(); if (info.Length() < 5) { @@ -291,12 +292,12 @@ if (info.Length() == 6) } if (mRenderContext) { - mRenderContext->getCtx()->Arc(x, y, r, startAngle, endAngle, clockwise); + mRenderContext->getCtx2d()->Arc(x, y, r, startAngle, endAngle, clockwise); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(arcTo) +DEFINE_VOID_METHOD(arcTo) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 5); @@ -307,23 +308,23 @@ float y2 = info[3].As().FloatValue(); float r = info[4].As().FloatValue(); if (mRenderContext) { - mRenderContext->getCtx()->ArcTo(x1, y1, x2, y2, r); + mRenderContext->getCtx2d()->ArcTo(x1, y1, x2, y2, r); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(beginPath) +DEFINE_VOID_METHOD(beginPath) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 0); if (mRenderContext) { - mRenderContext->getCtx()->BeginPath(); + mRenderContext->getCtx2d()->BeginPath(); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(bezierCurveTo) +DEFINE_VOID_METHOD(bezierCurveTo) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 6); @@ -335,12 +336,12 @@ float x = info[4].As().FloatValue(); float y = info[5].As().FloatValue(); if (mRenderContext) { - mRenderContext->getCtx()->BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); + mRenderContext->getCtx2d()->BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(clip) +DEFINE_VOID_METHOD(clip) Napi::Env env = info.Env(); GFillRule rule = FILL_RULE_NONZERO; @@ -363,18 +364,18 @@ if (info.Length() == 1) if (mRenderContext) { - mRenderContext->getCtx()->Clip(rule); + mRenderContext->getCtx2d()->Clip(rule); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(closePath) +DEFINE_VOID_METHOD(closePath) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 0); if (mRenderContext) { - mRenderContext->getCtx()->ClosePath(); + mRenderContext->getCtx2d()->ClosePath(); } RECORD_TIME_END } @@ -410,7 +411,7 @@ NodeBinding::checkArgs(info, 6); return Gradient::NewInstance(env, info); } -DEFINE_VOID_METHOD_BEGIN(drawImage) +DEFINE_VOID_METHOD(drawImage) Napi::Env env = info.Env(); if (info.Length() < 3 || (info.Length() != 3 && info.Length() != 5 && info.Length() != 9)) { @@ -457,8 +458,8 @@ if (name.IsString()) //fixme later canvas->mRenderContext->BindFBO(); - canvas->mRenderContext->getCtx()->GetImageData(0, 0, textureWidth, textureHeight, pixels); - textureId = canvas->mRenderContext->getCtx()->BindImage(pixels, GL_RGBA, textureWidth, textureHeight); + canvas->mRenderContext->getCtx2d()->GetImageData(0, 0, textureWidth, textureHeight, pixels); + textureId = canvas->mRenderContext->getCtx2d()->BindImage(pixels, GL_RGBA, textureWidth, textureHeight); printf("drawImage with canvas, textureId=%d, textureWidth=%d, textureHeight=%d\n", textureId, textureWidth, textureHeight); delete[] pixels; @@ -476,7 +477,7 @@ if (name.IsString()) int id = mRenderContext->getTextureIdByUrl(image->getUrl()); if (id == -1) { - id = mRenderContext->getCtx()->BindImage(&image->getPixels()[0], GL_RGBA, srcWidth, srcHeight); + id = mRenderContext->getCtx2d()->BindImage(&image->getPixels()[0], GL_RGBA, srcWidth, srcHeight); //缓存下url和纹理id的关系,避免重复bind mRenderContext->recordImageTexture(image->getUrl(), id); } @@ -518,7 +519,7 @@ else if (info.Length() == 9) } if (mRenderContext) { - mRenderContext->getCtx()->DrawImage(textureId, + mRenderContext->getCtx2d()->DrawImage(textureId, textureWidth, textureHeight, // image width & height srcX, // srcX @@ -533,7 +534,7 @@ if (mRenderContext) } } -DEFINE_VOID_METHOD_BEGIN(fill) +DEFINE_VOID_METHOD(fill) Napi::Env env = info.Env(); GFillRule rule = FILL_RULE_NONZERO; @@ -555,12 +556,12 @@ if (info.Length() == 1) } if (mRenderContext) { - mRenderContext->getCtx()->Fill(rule); + mRenderContext->getCtx2d()->Fill(rule); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(fillText) +DEFINE_VOID_METHOD(fillText) Napi::Env env = info.Env(); if (info.Length() < 3) @@ -576,11 +577,11 @@ if (mRenderContext) if (info.Length() == 4) { float maxWidth = info[3].As().FloatValue(); - mRenderContext->getCtx()->DrawText(content.c_str(), x, y, maxWidth); + mRenderContext->getCtx2d()->DrawText(content.c_str(), x, y, maxWidth); } else { - mRenderContext->getCtx()->DrawText(content.c_str(), x, y); + mRenderContext->getCtx2d()->DrawText(content.c_str(), x, y); } } RECORD_TIME_END @@ -602,7 +603,7 @@ if (mRenderContext) Napi::Object imageDataObj = ImageData::NewInstance(env, info[2], info[3]); ImageData *ptr = Napi::ObjectWrap::Unwrap(imageDataObj); - mRenderContext->getCtx()->GetImageData(x, y, width, height, &ptr->getPixles()[0]); + mRenderContext->getCtx2d()->GetImageData(x, y, width, height, &ptr->getPixles()[0]); //flipY gcanvas::FlipPixel(&ptr->getPixles()[0], width, height); @@ -619,7 +620,7 @@ NodeBinding::checkArgs(info, 0); Napi::Array ret = Napi::Array::New(env); if (mRenderContext) { - std::vector dash = mRenderContext->getCtx()->LineDash(); + std::vector dash = mRenderContext->getCtx2d()->LineDash(); for (int i = 0; i < dash.size(); i++) { ret.Set(i, Napi::Number::New(env, dash[i])); @@ -629,14 +630,14 @@ RECORD_TIME_END return ret; } -DEFINE_VOID_METHOD_BEGIN(lineTo) +DEFINE_VOID_METHOD(lineTo) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 2); float x = info[0].As().FloatValue(); float y = info[1].As().FloatValue(); if (mRenderContext) { - mRenderContext->getCtx()->LineTo(x, y); + mRenderContext->getCtx2d()->LineTo(x, y); } RECORD_TIME_END } @@ -648,7 +649,7 @@ NodeBinding::checkArgs(info, 1); std::string text = info[0].As().Utf8Value(); if (mRenderContext) { - float width = mRenderContext->getCtx()->MeasureTextWidth(text.c_str()); + float width = mRenderContext->getCtx2d()->MeasureTextWidth(text.c_str()); return TextMetrics::NewInstance(env, Napi::Number::New(env, width)); } else @@ -658,7 +659,7 @@ else RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(moveTo) +DEFINE_VOID_METHOD(moveTo) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 2); @@ -666,12 +667,12 @@ float x = info[0].As().FloatValue(); float y = info[1].As().FloatValue(); if (mRenderContext) { - mRenderContext->getCtx()->MoveTo(x, y); + mRenderContext->getCtx2d()->MoveTo(x, y); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(putImageData) +DEFINE_VOID_METHOD(putImageData) Napi::Env env = info.Env(); if (info.Length() < 3) { @@ -700,7 +701,7 @@ if (mRenderContext) dirtyWidth = info[5].As().Int32Value(); dirtyHeight = info[6].As().Int32Value(); } - mRenderContext->getCtx()->PutImageData( + mRenderContext->getCtx2d()->PutImageData( &imgData->getPixles()[0], //content imgData->getWidth(), //imageData width imgData->getHeight(), //imageData height @@ -715,7 +716,7 @@ if (mRenderContext) RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(quadraticCurveTo) +DEFINE_VOID_METHOD(quadraticCurveTo) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 4); float cpx = info[0].As().FloatValue(); @@ -724,12 +725,12 @@ float x = info[2].As().FloatValue(); float y = info[3].As().FloatValue(); if (mRenderContext) { - mRenderContext->getCtx()->QuadraticCurveTo(cpx, cpy, x, y); + mRenderContext->getCtx2d()->QuadraticCurveTo(cpx, cpy, x, y); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(rect) +DEFINE_VOID_METHOD(rect) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 4); @@ -739,66 +740,66 @@ float width = info[2].As().FloatValue(); float height = info[3].As().FloatValue(); if (mRenderContext) { - mRenderContext->getCtx()->Rect(x, y, width, height); + mRenderContext->getCtx2d()->Rect(x, y, width, height); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(resetTransform) +DEFINE_VOID_METHOD(resetTransform) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 0); if (mRenderContext) { - mRenderContext->getCtx()->ResetTransform(); + mRenderContext->getCtx2d()->ResetTransform(); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(restore) +DEFINE_VOID_METHOD(restore) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 0); if (mRenderContext) { - mRenderContext->getCtx()->Restore(); + mRenderContext->getCtx2d()->Restore(); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(rotate) +DEFINE_VOID_METHOD(rotate) Napi::Env env = info.Env(); float angle = info[0].As().FloatValue(); NodeBinding::checkArgs(info, 1); if (mRenderContext) { - mRenderContext->getCtx()->Rotate(angle); + mRenderContext->getCtx2d()->Rotate(angle); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(save) +DEFINE_VOID_METHOD(save) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 0); if (mRenderContext) { - mRenderContext->getCtx()->Save(); + mRenderContext->getCtx2d()->Save(); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(scale) +DEFINE_VOID_METHOD(scale) Napi::Env env = info.Env(); float x = info[0].As().FloatValue(); float y = info[1].As().FloatValue(); NodeBinding::checkArgs(info, 2); if (mRenderContext) { - mRenderContext->getCtx()->Scale(x, y); + mRenderContext->getCtx2d()->Scale(x, y); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(setLineDash) +DEFINE_VOID_METHOD(setLineDash) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 1); Napi::Array array = info[0].As(); @@ -810,7 +811,7 @@ for (int i = 0; i < array.Length(); i++) } if (mRenderContext) { - mRenderContext->getCtx()->SetLineDash(std::move(dash)); + mRenderContext->getCtx2d()->SetLineDash(std::move(dash)); } RECORD_TIME_END } @@ -819,7 +820,7 @@ void Context2D::setCanvasRef(NodeBinding::Canvas *canvas) { this->mCanvas = canvas; } -DEFINE_VOID_METHOD_BEGIN(setTransform) +DEFINE_VOID_METHOD(setTransform) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 6); @@ -832,23 +833,23 @@ float translateX = info[4].As().FloatValue(); float translateY = info[5].As().FloatValue(); if (mRenderContext) { - mRenderContext->getCtx()->SetTransform(scaleX, scaleY, rotateX, rototaY, translateX, translateY); + mRenderContext->getCtx2d()->SetTransform(scaleX, scaleY, rotateX, rototaY, translateX, translateY); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(stroke) +DEFINE_VOID_METHOD(stroke) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 0); if (mRenderContext) { - mRenderContext->getCtx()->Stroke(); + mRenderContext->getCtx2d()->Stroke(); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(strokeRect) +DEFINE_VOID_METHOD(strokeRect) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 4); float x = info[0].As().FloatValue(); @@ -857,12 +858,12 @@ float width = info[2].As().FloatValue(); float height = info[3].As().FloatValue(); if (mRenderContext) { - mRenderContext->getCtx()->StrokeRect(x, y, width, height); + mRenderContext->getCtx2d()->StrokeRect(x, y, width, height); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(strokeText) +DEFINE_VOID_METHOD(strokeText) Napi::Env env = info.Env(); if (info.Length() < 3) { @@ -877,17 +878,17 @@ if (mRenderContext) if (info.Length() == 4) { float maxWidth = info[3].As().FloatValue(); - mRenderContext->getCtx()->StrokeText(content.c_str(), x, y, maxWidth); + mRenderContext->getCtx2d()->StrokeText(content.c_str(), x, y, maxWidth); } else { - mRenderContext->getCtx()->StrokeText(content.c_str(), x, y); + mRenderContext->getCtx2d()->StrokeText(content.c_str(), x, y); } } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(transform) +DEFINE_VOID_METHOD(transform) Napi::Env env = info.Env(); NodeBinding::checkArgs(info, 6); @@ -900,19 +901,19 @@ float translateY = info[5].As().FloatValue(); // printf("the Transfrom called scaleX %f scaleY %f rotateX %f rototaY %f translateX %f translateY %f \n",scaleX,scaleY,rotateX,rotateY,translateX,translateY); if (mRenderContext) { - mRenderContext->getCtx()->Transfrom(scaleX, rotateX, rotateY, scaleY, translateX, translateY); + mRenderContext->getCtx2d()->Transfrom(scaleX, rotateX, rotateY, scaleY, translateX, translateY); } RECORD_TIME_END } -DEFINE_VOID_METHOD_BEGIN(translate) +DEFINE_VOID_METHOD(translate) Napi::Env env = info.Env(); float tx = info[0].As().FloatValue(); float ty = info[1].As().FloatValue(); NodeBinding::checkArgs(info, 2); if (mRenderContext) { - mRenderContext->getCtx()->Translate(tx, ty); + mRenderContext->getCtx2d()->Translate(tx, ty); } RECORD_TIME_END } @@ -922,7 +923,7 @@ std::string font = value.As().Utf8Value(); // printf("the set fon value is %s \n",font.c_str()); if (mRenderContext) { - mRenderContext->getCtx()->SetFont(font.c_str()); + mRenderContext->getCtx2d()->SetFont(font.c_str()); } RECORD_TIME_END } @@ -931,7 +932,7 @@ DEFINE_SETTER_METHOD(setglobalAlpha) float colorValue = info[0].As().FloatValue(); if (mRenderContext) { - mRenderContext->getCtx()->SetGlobalAlpha(colorValue); + mRenderContext->getCtx2d()->SetGlobalAlpha(colorValue); } RECORD_TIME_END } @@ -943,35 +944,35 @@ if (mRenderContext) { if (opValue == "source-over") { - mRenderContext->getCtx()->DoSetGlobalCompositeOperation(COMPOSITE_OP_SOURCE_OVER); + mRenderContext->getCtx2d()->DoSetGlobalCompositeOperation(COMPOSITE_OP_SOURCE_OVER); } else if (opValue == "source-out") { - mRenderContext->getCtx()->DoSetGlobalCompositeOperation(COMPOSITE_OP_SOURCE_OUT); + mRenderContext->getCtx2d()->DoSetGlobalCompositeOperation(COMPOSITE_OP_SOURCE_OUT); } else if (opValue == "source-atop") { - mRenderContext->getCtx()->DoSetGlobalCompositeOperation(COMPOSITE_OP_SOURCE_ATOP); + mRenderContext->getCtx2d()->DoSetGlobalCompositeOperation(COMPOSITE_OP_SOURCE_ATOP); } else if (opValue == "destination-over") { - mRenderContext->getCtx()->DoSetGlobalCompositeOperation(COMPOSITE_OP_DESTINATION_OVER); + mRenderContext->getCtx2d()->DoSetGlobalCompositeOperation(COMPOSITE_OP_DESTINATION_OVER); } else if (opValue == "destination-in") { - mRenderContext->getCtx()->DoSetGlobalCompositeOperation(COMPOSITE_OP_DESTINATION_IN); + mRenderContext->getCtx2d()->DoSetGlobalCompositeOperation(COMPOSITE_OP_DESTINATION_IN); } else if (opValue == "destination-out") { - mRenderContext->getCtx()->DoSetGlobalCompositeOperation(COMPOSITE_OP_DESTINATION_OUT); + mRenderContext->getCtx2d()->DoSetGlobalCompositeOperation(COMPOSITE_OP_DESTINATION_OUT); } else if (opValue == "lighter") { - mRenderContext->getCtx()->DoSetGlobalCompositeOperation(COMPOSITE_OP_LIGHTER); + mRenderContext->getCtx2d()->DoSetGlobalCompositeOperation(COMPOSITE_OP_LIGHTER); } else if (opValue == "xor") { - mRenderContext->getCtx()->DoSetGlobalCompositeOperation(COMPOSITE_OP_XOR); + mRenderContext->getCtx2d()->DoSetGlobalCompositeOperation(COMPOSITE_OP_XOR); } else { @@ -985,7 +986,7 @@ DEFINE_SETTER_METHOD(setlineCap) std::string lineCap = info[0].As().Utf8Value(); if (mRenderContext) { - mRenderContext->getCtx()->SetLineCap(lineCap.c_str()); + mRenderContext->getCtx2d()->SetLineCap(lineCap.c_str()); } RECORD_TIME_END } @@ -994,7 +995,7 @@ DEFINE_SETTER_METHOD(setlineDashOffset) if (mRenderContext) { float offset = info[0].As().FloatValue(); - mRenderContext->getCtx()->SetLineDashOffset(offset); + mRenderContext->getCtx2d()->SetLineDashOffset(offset); } RECORD_TIME_END } @@ -1003,7 +1004,7 @@ DEFINE_SETTER_METHOD(setlineJoin) std::string lineJoin = info[0].As().Utf8Value(); if (mRenderContext) { - mRenderContext->getCtx()->SetLineJoin(lineJoin.c_str()); + mRenderContext->getCtx2d()->SetLineJoin(lineJoin.c_str()); } RECORD_TIME_END } @@ -1012,7 +1013,7 @@ DEFINE_SETTER_METHOD(setlineWidth) float lineWidth = info[0].As().FloatValue(); if (mRenderContext) { - mRenderContext->getCtx()->SetLineWidth(lineWidth); + mRenderContext->getCtx2d()->SetLineWidth(lineWidth); } RECORD_TIME_END } @@ -1021,7 +1022,7 @@ DEFINE_SETTER_METHOD(setmiterLimit) float miterLimit = info[0].As().FloatValue(); if (mRenderContext) { - mRenderContext->getCtx()->SetMiterLimit(miterLimit); + mRenderContext->getCtx2d()->SetMiterLimit(miterLimit); } RECORD_TIME_END } @@ -1030,7 +1031,7 @@ DEFINE_SETTER_METHOD(setshadowBlur) float shadowBlur = info[0].As().FloatValue(); if (mRenderContext) { - mRenderContext->getCtx()->SetShadowBlur(shadowBlur); + mRenderContext->getCtx2d()->SetShadowBlur(shadowBlur); } RECORD_TIME_END } @@ -1039,7 +1040,7 @@ DEFINE_SETTER_METHOD(setshadowColor) std::string color = info[0].As().Utf8Value(); if (mRenderContext) { - mRenderContext->getCtx()->SetShadowColor(color.c_str()); + mRenderContext->getCtx2d()->SetShadowColor(color.c_str()); } RECORD_TIME_END } @@ -1048,7 +1049,7 @@ DEFINE_SETTER_METHOD(setshadowOffsetX) float offsetX = info[0].As().FloatValue(); if (mRenderContext) { - mRenderContext->getCtx()->SetShadowOffsetX(offsetX); + mRenderContext->getCtx2d()->SetShadowOffsetX(offsetX); } RECORD_TIME_END } @@ -1057,7 +1058,7 @@ DEFINE_SETTER_METHOD(setshadowOffsetY) float offsetY = info[0].As().FloatValue(); if (mRenderContext) { - mRenderContext->getCtx()->SetShadowOffsetY(offsetY); + mRenderContext->getCtx2d()->SetShadowOffsetY(offsetY); } RECORD_TIME_END } @@ -1068,7 +1069,7 @@ if (mRenderContext) if (value.IsString()) { std::string arg = value.As().Utf8Value(); - mRenderContext->getCtx()->SetStrokeStyle(arg.c_str()); + mRenderContext->getCtx2d()->SetStrokeStyle(arg.c_str()); } else if (value.IsObject()) { @@ -1093,7 +1094,7 @@ if (mRenderContext) offsetArray[i] = colorStop[i].offset; colorArray[i] = colorStop[i].color; } - mRenderContext->getCtx()->SetFillStyleLinearGradient(startArr, endArr, gradient->getCount(), offsetArray, colorArray, true); + mRenderContext->getCtx2d()->SetFillStyleLinearGradient(startArr, endArr, gradient->getCount(), offsetArray, colorArray, true); } else if (namePropetry == "radialGradient") { @@ -1108,17 +1109,17 @@ if (mRenderContext) offsetArray[i] = colorStop[i].offset; colorArray[i] = colorStop[i].color; } - mRenderContext->getCtx()->SetFillStyleRadialGradient(startArr, endArr, gradient->getCount(), offsetArray, colorArray, true); + mRenderContext->getCtx2d()->SetFillStyleRadialGradient(startArr, endArr, gradient->getCount(), offsetArray, colorArray, true); } else if (namePropetry == "pattern") { Pattern *pattern = Napi::ObjectWrap::Unwrap(object); - int textureId = mRenderContext->getCtx()->BindImage( + int textureId = mRenderContext->getCtx2d()->BindImage( &pattern->content->getPixels()[0], GL_RGBA, pattern->content->getWidth(), pattern->content->getHeight()); - mRenderContext->getCtx()->SetFillStylePattern( + mRenderContext->getCtx2d()->SetFillStylePattern( textureId, pattern->content->getWidth(), pattern->content->getHeight(), pattern->getRepetition().c_str(), true); @@ -1140,23 +1141,23 @@ if (mRenderContext) { if (textAlign == "start") { - mRenderContext->getCtx()->SetTextAlign(TEXT_ALIGN_START); + mRenderContext->getCtx2d()->SetTextAlign(TEXT_ALIGN_START); } else if (textAlign == "end") { - mRenderContext->getCtx()->SetTextAlign(TEXT_ALIGN_END); + mRenderContext->getCtx2d()->SetTextAlign(TEXT_ALIGN_END); } else if (textAlign == "left") { - mRenderContext->getCtx()->SetTextAlign(TEXT_ALIGN_LEFT); + mRenderContext->getCtx2d()->SetTextAlign(TEXT_ALIGN_LEFT); } else if (textAlign == "center") { - mRenderContext->getCtx()->SetTextAlign(TEXT_ALIGN_CENTER); + mRenderContext->getCtx2d()->SetTextAlign(TEXT_ALIGN_CENTER); } else if (textAlign == "right") { - mRenderContext->getCtx()->SetTextAlign(TEXT_ALIGN_RIGHT); + mRenderContext->getCtx2d()->SetTextAlign(TEXT_ALIGN_RIGHT); } else { @@ -1172,23 +1173,23 @@ if (mRenderContext) { if (baseline == "top") { - mRenderContext->getCtx()->SetTextBaseline(TEXT_BASELINE_TOP); + mRenderContext->getCtx2d()->SetTextBaseline(TEXT_BASELINE_TOP); } else if (baseline == "bottom") { - mRenderContext->getCtx()->SetTextBaseline(TEXT_BASELINE_BOTTOM); + mRenderContext->getCtx2d()->SetTextBaseline(TEXT_BASELINE_BOTTOM); } else if (baseline == "middle") { - mRenderContext->getCtx()->SetTextBaseline(TEXT_BASELINE_MIDDLE); + mRenderContext->getCtx2d()->SetTextBaseline(TEXT_BASELINE_MIDDLE); } else if (baseline == "alphabetic") { - mRenderContext->getCtx()->SetTextBaseline(TEXT_BASELINE_ALPHABETIC); + mRenderContext->getCtx2d()->SetTextBaseline(TEXT_BASELINE_ALPHABETIC); } else if (baseline == "hanging") { - mRenderContext->getCtx()->SetTextBaseline(TEXT_BASELINE_HANGING); + mRenderContext->getCtx2d()->SetTextBaseline(TEXT_BASELINE_HANGING); } else { @@ -1202,7 +1203,7 @@ DEFINE_GETTER_METHOD(getfont) Napi::Env env = info.Env(); if (mRenderContext) { - std::string value = mRenderContext->getCtx()->mCurrentState->mFont->GetOriginFontName(); + std::string value = mRenderContext->getCtx2d()->mCurrentState->mFont->GetOriginFontName(); return Napi::String::New(env, value); } RECORD_TIME_END @@ -1213,7 +1214,7 @@ DEFINE_GETTER_METHOD(getglobalAlpha) Napi::Env env = info.Env(); if (mRenderContext) { - float value = mRenderContext->getCtx()->GlobalAlpha(); + float value = mRenderContext->getCtx2d()->GlobalAlpha(); return Napi::Number::New(env, value); } RECORD_TIME_END @@ -1224,7 +1225,7 @@ DEFINE_GETTER_METHOD(getglobalCompositeOperation) Napi::Env env = info.Env(); if (mRenderContext) { - GCompositeOperation value = mRenderContext->getCtx()->GlobalCompositeOperation(); + GCompositeOperation value = mRenderContext->getCtx2d()->GlobalCompositeOperation(); if (value == COMPOSITE_OP_SOURCE_OVER) { return Napi::String::New(env, "source-over"); @@ -1266,7 +1267,7 @@ DEFINE_GETTER_METHOD(getlineCap) Napi::Env env = info.Env(); if (mRenderContext) { - GLineCap cap = mRenderContext->getCtx()->LineCap(); + GLineCap cap = mRenderContext->getCtx2d()->LineCap(); if (cap == LINE_CAP_BUTT) { return Napi::String::New(env, "butt"); @@ -1288,7 +1289,7 @@ DEFINE_GETTER_METHOD(getlineDashOffset) Napi::Env env = info.Env(); if (mRenderContext) { - float value = mRenderContext->getCtx()->LineDashOffset(); + float value = mRenderContext->getCtx2d()->LineDashOffset(); return Napi::Number::New(env, value); } RECORD_TIME_END @@ -1299,7 +1300,7 @@ DEFINE_GETTER_METHOD(getlineJoin) Napi::Env env = info.Env(); if (mRenderContext) { - GLineJoin value = mRenderContext->getCtx()->LineJoin(); + GLineJoin value = mRenderContext->getCtx2d()->LineJoin(); if (value == LINE_JOIN_BEVEL) { return Napi::String::New(env, "bevel"); @@ -1321,7 +1322,7 @@ DEFINE_GETTER_METHOD(getlineWidth) Napi::Env env = info.Env(); if (mRenderContext) { - return Napi::Number::New(env, mRenderContext->getCtx()->LineWidth()); + return Napi::Number::New(env, mRenderContext->getCtx2d()->LineWidth()); } RECORD_TIME_END return Napi::Number::New(env, -1); @@ -1331,7 +1332,7 @@ DEFINE_GETTER_METHOD(getmiterLimit) Napi::Env env = info.Env(); if (mRenderContext) { - float value = mRenderContext->getCtx()->MiterLimit(); + float value = mRenderContext->getCtx2d()->MiterLimit(); return Napi::Number::New(env, value); } RECORD_TIME_END @@ -1342,7 +1343,7 @@ DEFINE_GETTER_METHOD(getshadowBlur) Napi::Env env = info.Env(); if (mRenderContext) { - return Napi::Number::New(env, mRenderContext->getCtx()->mCurrentState->mShadowBlur); + return Napi::Number::New(env, mRenderContext->getCtx2d()->mCurrentState->mShadowBlur); } RECORD_TIME_END return Napi::String::New(env, ""); @@ -1352,7 +1353,7 @@ DEFINE_GETTER_METHOD(getshadowColor) Napi::Env env = info.Env(); if (mRenderContext) { - return Napi::String::New(env, gcanvas::ColorToString(mRenderContext->getCtx()->mCurrentState->mShadowColor)); + return Napi::String::New(env, gcanvas::ColorToString(mRenderContext->getCtx2d()->mCurrentState->mShadowColor)); } RECORD_TIME_END return Napi::String::New(env, ""); @@ -1362,7 +1363,7 @@ DEFINE_GETTER_METHOD(getshadowOffsetX) Napi::Env env = info.Env(); if (mRenderContext) { - return Napi::Number::New(env, mRenderContext->getCtx()->mCurrentState->mShadowOffsetX); + return Napi::Number::New(env, mRenderContext->getCtx2d()->mCurrentState->mShadowOffsetX); } RECORD_TIME_END return Napi::Number::New(env, -1); @@ -1372,7 +1373,7 @@ DEFINE_GETTER_METHOD(getshadowOffsetY) Napi::Env env = info.Env(); if (mRenderContext) { - return Napi::Number::New(env, mRenderContext->getCtx()->mCurrentState->mShadowOffsetY); + return Napi::Number::New(env, mRenderContext->getCtx2d()->mCurrentState->mShadowOffsetY); } RECORD_TIME_END return Napi::String::New(env, ""); @@ -1382,7 +1383,7 @@ DEFINE_GETTER_METHOD(getstrokeStyle) Napi::Env env = info.Env(); if (mRenderContext) { - return Napi::String::New(env, gcanvas::ColorToString(mRenderContext->getCtx()->StrokeStyle())); + return Napi::String::New(env, gcanvas::ColorToString(mRenderContext->getCtx2d()->StrokeStyle())); } RECORD_TIME_END return Napi::String::New(env, ""); @@ -1392,7 +1393,7 @@ DEFINE_GETTER_METHOD(gettextAlign) Napi::Env env = info.Env(); if (mRenderContext) { - GTextAlign value = mRenderContext->getCtx()->TextAlign(); + GTextAlign value = mRenderContext->getCtx2d()->TextAlign(); if (value == TEXT_ALIGN_LEFT) { return Napi::String::New(env, "left"); @@ -1422,7 +1423,7 @@ DEFINE_GETTER_METHOD(gettextBaseline) Napi::Env env = info.Env(); if (mRenderContext) { - GTextBaseline value = mRenderContext->getCtx()->TextBaseline(); + GTextBaseline value = mRenderContext->getCtx2d()->TextBaseline(); if (value == TEXT_BASELINE_TOP) { return Napi::String::New(env, "top"); diff --git a/node/binding/CanvasRenderingContextWebGL.cc b/node/binding/CanvasRenderingContextWebGL.cc new file mode 100644 index 00000000..5ec16909 --- /dev/null +++ b/node/binding/CanvasRenderingContextWebGL.cc @@ -0,0 +1,2473 @@ +#include "CanvasRenderingContextWebGL.h" +#include "./webgl/WebGLShader.h" +#include "./webgl/WebGLProgram.h" +#include "./webgl/WebGLBuffer.h" +#include "./webgl/WebGLTexture.h" +#include "./webgl/WebGLFrameBuffer.h" +#include "./webgl/WebGLRenderBuffer.h" +#include "./webgl/WebGLActiveInfo.h" +#include "./webgl/WebGLUniformLocation.h" +#include "Image.h" + + +// #define ENABLE_RECORD_COST_TIME +#ifdef ENABLE_RECORD_COST_TIME +#define RECORD_TIME_BEGIN \ + clock_t start, finish; \ + start = clock(); +#define RECORD_TIME_END \ + finish = clock(); \ + printf("[%s]cost time %.5f ms, \n", __FUNCTION__, (double)(finish - start) * 1000.0f / CLOCKS_PER_SEC); +#else +#define RECORD_TIME_BEGIN +#define RECORD_TIME_END +#endif + +#define EGL_MAKE_CURRENT mRenderContext->makeCurrent(); + + +#define DEFINE_VOID_METHOD(methodName) void ContextWebGL::methodName(const Napi::CallbackInfo &info) + +#define DEFINE_RETURN_VALUE_METHOD(methodName) Napi::Value ContextWebGL::methodName(const Napi::CallbackInfo &info) + + + +namespace NodeBinding +{ + static float parseFloat(const Napi::Value& value) + { + float ret = 0.0f; + if (value.IsNumber()) + { + ret = value.As().FloatValue(); + } + else if (value.IsBoolean()) + { + ret = value.As().Value(); + } + return ret; + } + + static int parseInt(const Napi::Value &value) + { + int ret = 0; + if (value.IsNumber()) + { + ret = value.As().Int32Value(); + } + else if (value.IsBoolean()) + { + ret = value.As().Value(); + } + return ret; + } + + static GLuint parseUInt(const Napi::Value& value) + { + GLuint ret = 0; + if (value.IsNumber()) + { + ret = value.As().Uint32Value(); + } + else if (value.IsBoolean()) + { + ret = value.As().Value(); + } + return ret; + } + Napi::FunctionReference ContextWebGL::constructor; + void ContextWebGL::Init(Napi::Env env) + { + Napi::HandleScope scope(env); + Napi::Function func = + DefineClass(env, + "ContextWebGL", + { + BINDING_OBJECT_METHOD(createBuffer), + BINDING_OBJECT_METHOD(createProgram), + BINDING_OBJECT_METHOD(createTexture), + BINDING_OBJECT_METHOD(createShader), + BINDING_OBJECT_METHOD(createFrameBuffer), + BINDING_OBJECT_METHOD(createRenderBuffer), + + BINDING_OBJECT_METHOD(deleteShader), + BINDING_OBJECT_METHOD(deleteProgram), + BINDING_OBJECT_METHOD(deleteFrameBuffer), + BINDING_OBJECT_METHOD(deleteRenderBuffer), + BINDING_OBJECT_METHOD(deleteTexture), + BINDING_OBJECT_METHOD(deleteBuffer), + + BINDING_OBJECT_METHOD(isBuffer), + BINDING_OBJECT_METHOD(isFramebuffer), + BINDING_OBJECT_METHOD(isTexture), + BINDING_OBJECT_METHOD(isShader), + BINDING_OBJECT_METHOD(isProgram), + BINDING_OBJECT_METHOD(isRenderBuffer), + + BINDING_OBJECT_METHOD(getShaderParameter), + BINDING_OBJECT_METHOD(getProgramParameter), + BINDING_OBJECT_METHOD(getBufferParameter), + BINDING_OBJECT_METHOD(getTexParameter), + BINDING_OBJECT_METHOD(getFramebufferAttachmentParameter), + + BINDING_OBJECT_METHOD(viewport), + BINDING_OBJECT_METHOD(scissor), + BINDING_OBJECT_METHOD(clearColor), + BINDING_OBJECT_METHOD(colorMask), + BINDING_OBJECT_METHOD(clearDepth), + BINDING_OBJECT_METHOD(clearStencil), + + BINDING_OBJECT_METHOD(bindBuffer), + BINDING_OBJECT_METHOD(bufferData), + BINDING_OBJECT_METHOD(bufferSubData), + + BINDING_OBJECT_METHOD(bindTexture), + BINDING_OBJECT_METHOD(renderbufferStorage), + + BINDING_OBJECT_METHOD(shaderSource), + BINDING_OBJECT_METHOD(getShaderSource), + BINDING_OBJECT_METHOD(compileShader), + BINDING_OBJECT_METHOD(attachShader), + BINDING_OBJECT_METHOD(detachShader), + BINDING_OBJECT_METHOD(getAttachedShaders), + BINDING_OBJECT_METHOD(linkProgram), + BINDING_OBJECT_METHOD(useProgram), + BINDING_OBJECT_METHOD(validateProgram), + + BINDING_OBJECT_METHOD(vertexAttribPointer), + BINDING_OBJECT_METHOD(enableVertexAttribArray), + BINDING_OBJECT_METHOD(disableVertexAttribArray), + + BINDING_OBJECT_METHOD(bindFramebuffer), + BINDING_OBJECT_METHOD(checkFramebufferStatus), + BINDING_OBJECT_METHOD(framebufferRenderbuffer), + BINDING_OBJECT_METHOD(framebufferTexture2D), + + BINDING_OBJECT_METHOD(drawElements), + BINDING_OBJECT_METHOD(drawArrays), + BINDING_OBJECT_METHOD(flush), + BINDING_OBJECT_METHOD(finish), + BINDING_OBJECT_METHOD(clear), + + BINDING_OBJECT_METHOD(getAttribLocation), + BINDING_OBJECT_METHOD(getShaderInfoLog), + BINDING_OBJECT_METHOD(bindAttribLocation), + BINDING_OBJECT_METHOD(getUniformLocation), + BINDING_OBJECT_METHOD(getActiveAttrib), + BINDING_OBJECT_METHOD(getActiveUniform), + BINDING_OBJECT_METHOD(getUniform), + BINDING_OBJECT_METHOD(getVertexAttrib), + BINDING_OBJECT_METHOD(getVertexAttribOffset), + + BINDING_OBJECT_METHOD(uniform1f), + BINDING_OBJECT_METHOD(uniform2f), + BINDING_OBJECT_METHOD(uniform3f), + BINDING_OBJECT_METHOD(uniform4f), + + BINDING_OBJECT_METHOD(uniform1i), + BINDING_OBJECT_METHOD(uniform2i), + BINDING_OBJECT_METHOD(uniform3i), + BINDING_OBJECT_METHOD(uniform4i), + + BINDING_OBJECT_METHOD(uniform1fv), + BINDING_OBJECT_METHOD(uniform2fv), + BINDING_OBJECT_METHOD(uniform3fv), + BINDING_OBJECT_METHOD(uniform4fv), + + BINDING_OBJECT_METHOD(uniform1iv), + BINDING_OBJECT_METHOD(uniform2iv), + BINDING_OBJECT_METHOD(uniform3iv), + BINDING_OBJECT_METHOD(uniform4iv), + + BINDING_OBJECT_METHOD(uniformMatrix2fv), + BINDING_OBJECT_METHOD(uniformMatrix3fv), + BINDING_OBJECT_METHOD(uniformMatrix4fv), + + BINDING_OBJECT_METHOD(vertexAttrib1f), + BINDING_OBJECT_METHOD(vertexAttrib2f), + BINDING_OBJECT_METHOD(vertexAttrib3f), + BINDING_OBJECT_METHOD(vertexAttrib4f), + + BINDING_OBJECT_METHOD(vertexAttrib1fv), + BINDING_OBJECT_METHOD(vertexAttrib2fv), + BINDING_OBJECT_METHOD(vertexAttrib3fv), + BINDING_OBJECT_METHOD(vertexAttrib4fv), + + BINDING_OBJECT_METHOD(activeTexture), + BINDING_OBJECT_METHOD(pixelStorei), + BINDING_OBJECT_METHOD(texParameteri), + BINDING_OBJECT_METHOD(texParameterf), + BINDING_OBJECT_METHOD(texImage2D), + + BINDING_OBJECT_METHOD(depthFunc), + BINDING_OBJECT_METHOD(depthMask), + BINDING_OBJECT_METHOD(depthRange), + + BINDING_OBJECT_METHOD(enable), + BINDING_OBJECT_METHOD(disable), + BINDING_OBJECT_METHOD(isEnabled), + + BINDING_OBJECT_METHOD(stencilFunc), + BINDING_OBJECT_METHOD(stencilOp), + BINDING_OBJECT_METHOD(stencilMask), + BINDING_OBJECT_METHOD(stencilOpSeparate), + BINDING_OBJECT_METHOD(stencilMaskSeparate), + BINDING_OBJECT_METHOD(stencilFuncSeparate), + + BINDING_OBJECT_METHOD(blendColor), + BINDING_OBJECT_METHOD(blendFunc), + BINDING_OBJECT_METHOD(blendFuncSeparate), + BINDING_OBJECT_METHOD(blendEquation), + BINDING_OBJECT_METHOD(blendEquationSeparate), + BINDING_OBJECT_METHOD(generateMipmap), + BINDING_OBJECT_METHOD(cullFace), + BINDING_OBJECT_METHOD(frontFace), + BINDING_OBJECT_METHOD(getError), + + BINDING_OBJECT_METHOD(polygonOffset), + BINDING_OBJECT_METHOD(lineWidth), + BINDING_OBJECT_METHOD(sampleCoverage), + BINDING_OBJECT_METHOD(hint), + BINDING_OBJECT_METHOD(isContextLost), + BINDING_OBJECT_METHOD(readPixels), + + BINDING_CONST_PROPERY(LINK_STATUS), + BINDING_CONST_PROPERY(COLOR_BUFFER_BIT), + BINDING_CONST_PROPERY(DEPTH_BUFFER_BIT), + BINDING_CONST_PROPERY(STENCIL_BUFFER_BIT), + BINDING_CONST_PROPERY(TRIANGLES), + BINDING_CONST_PROPERY(POINTS), + BINDING_CONST_PROPERY(LINE_STRIP), + BINDING_CONST_PROPERY(LINES), + BINDING_CONST_PROPERY(LINE_LOOP), + BINDING_CONST_PROPERY(TRIANGLE_FAN), + BINDING_CONST_PROPERY(TRIANGLE_STRIP), + + BINDING_CONST_PROPERY(DEPTH_TEST), + BINDING_CONST_PROPERY(SCISSOR_TEST), + BINDING_CONST_PROPERY(STENCIL_TEST), + + BINDING_CONST_PROPERY(COMPILE_STATUS), + BINDING_CONST_PROPERY(ARRAY_BUFFER), + BINDING_CONST_PROPERY(STATIC_DRAW), + BINDING_CONST_PROPERY(ELEMENT_ARRAY_BUFFER), + BINDING_CONST_PROPERY(VERTEX_SHADER), + BINDING_CONST_PROPERY(FRAGMENT_SHADER), + + BINDING_CONST_PROPERY(RGBA), + BINDING_CONST_PROPERY(RGBA4), + BINDING_CONST_PROPERY(DEPTH_COMPONENT), + BINDING_CONST_PROPERY(ALPHA), + BINDING_CONST_PROPERY(RGB5_A1), + BINDING_CONST_PROPERY(RGB565), + BINDING_CONST_PROPERY(LUMINANCE), + BINDING_CONST_PROPERY(LUMINANCE_ALPHA), + BINDING_CONST_PROPERY(DEPTH_COMPONENT16), + BINDING_CONST_PROPERY(STENCIL_INDEX8), + + BINDING_CONST_PROPERY(FLOAT), + BINDING_CONST_PROPERY(BYTE), + BINDING_CONST_PROPERY(UNSIGNED_BYTE), + BINDING_CONST_PROPERY(SHORT), + BINDING_CONST_PROPERY(UNSIGNED_SHORT), + BINDING_CONST_PROPERY(INT), + BINDING_CONST_PROPERY(UNSIGNED_INT), + BINDING_CONST_PROPERY(FLOAT), + + BINDING_CONST_PROPERY(FALSE), + BINDING_CONST_PROPERY(TRUE), + BINDING_CONST_PROPERY(ZERO), + BINDING_CONST_PROPERY(ONE), + + BINDING_CONST_PROPERY(CURRENT_VERTEX_ATTRIB), + BINDING_CONST_PROPERY(VERTEX_ATTRIB_ARRAY_ENABLED), + BINDING_CONST_PROPERY(VERTEX_ATTRIB_ARRAY_SIZE), + BINDING_CONST_PROPERY(VERTEX_ATTRIB_ARRAY_STRIDE), + BINDING_CONST_PROPERY(VERTEX_ATTRIB_ARRAY_TYPE), + BINDING_CONST_PROPERY(VERTEX_ATTRIB_ARRAY_NORMALIZED), + BINDING_CONST_PROPERY(VERTEX_ATTRIB_ARRAY_POINTER), + BINDING_CONST_PROPERY(VERTEX_ATTRIB_ARRAY_BUFFER_BINDING), + + BINDING_CONST_PROPERY(CULL_FACE), + BINDING_CONST_PROPERY(FRONT), + BINDING_CONST_PROPERY(BACK), + BINDING_CONST_PROPERY(FRONT_AND_BACK), + + // Enabling and disabling + BINDING_CONST_PROPERY(BLEND), + BINDING_CONST_PROPERY(DITHER), + BINDING_CONST_PROPERY(POLYGON_OFFSET_FILL), + BINDING_CONST_PROPERY(SAMPLE_ALPHA_TO_COVERAGE), + BINDING_CONST_PROPERY(SAMPLE_COVERAGE), + + // errors + BINDING_CONST_PROPERY(NO_ERROR), + BINDING_CONST_PROPERY(INVALID_ENUM), + BINDING_CONST_PROPERY(INVALID_VALUE), + BINDING_CONST_PROPERY(INVALID_OPERATION), + BINDING_CONST_PROPERY(OUT_OF_MEMORY), + // BINDING_CONST_PROPERY(CONTEXT_LOST_WEBGL), + + // Front face directions + BINDING_CONST_PROPERY(CW), + BINDING_CONST_PROPERY(CCW), + + BINDING_CONST_PROPERY(DONT_CARE), + BINDING_CONST_PROPERY(FASTEST), + BINDING_CONST_PROPERY(NICEST), + BINDING_CONST_PROPERY(GENERATE_MIPMAP_HINT), + + // Pixel types + // BIND_CONSTANT(UNSIGNED_BYTE, 0x1401), + BINDING_CONST_PROPERY(UNSIGNED_SHORT_4_4_4_4), + BINDING_CONST_PROPERY(UNSIGNED_SHORT_5_5_5_1), + BINDING_CONST_PROPERY(UNSIGNED_SHORT_5_6_5), + + BINDING_CONST_PROPERY(FLOAT_VEC2), + BINDING_CONST_PROPERY(FLOAT_VEC3), + BINDING_CONST_PROPERY(FLOAT_VEC4), + BINDING_CONST_PROPERY(INT_VEC2), + BINDING_CONST_PROPERY(INT_VEC3), + BINDING_CONST_PROPERY(INT_VEC4), + BINDING_CONST_PROPERY(BOOL), + BINDING_CONST_PROPERY(BOOL_VEC2), + BINDING_CONST_PROPERY(BOOL_VEC3), + BINDING_CONST_PROPERY(BOOL_VEC4), + BINDING_CONST_PROPERY(FLOAT_MAT2), + BINDING_CONST_PROPERY(FLOAT_MAT3), + BINDING_CONST_PROPERY(FLOAT_MAT4), + BINDING_CONST_PROPERY(SAMPLER_2D), + BINDING_CONST_PROPERY(SAMPLER_CUBE), + + BINDING_CONST_PROPERY(LOW_FLOAT), + BINDING_CONST_PROPERY(MEDIUM_FLOAT), + BINDING_CONST_PROPERY(HIGH_FLOAT), + BINDING_CONST_PROPERY(LOW_INT), + BINDING_CONST_PROPERY(MEDIUM_INT), + BINDING_CONST_PROPERY(HIGH_INT), + + BINDING_CONST_PROPERY(SRC_COLOR), + BINDING_CONST_PROPERY(ONE_MINUS_SRC_COLOR), + BINDING_CONST_PROPERY(SRC_ALPHA), + BINDING_CONST_PROPERY(ONE_MINUS_SRC_ALPHA), + BINDING_CONST_PROPERY(DST_ALPHA), + BINDING_CONST_PROPERY(ONE_MINUS_DST_ALPHA), + BINDING_CONST_PROPERY(DST_COLOR), + BINDING_CONST_PROPERY(ONE_MINUS_DST_COLOR), + BINDING_CONST_PROPERY(SRC_ALPHA_SATURATE), + BINDING_CONST_PROPERY(CONSTANT_COLOR), + BINDING_CONST_PROPERY(ONE_MINUS_CONSTANT_COLOR), + BINDING_CONST_PROPERY(CONSTANT_ALPHA), + BINDING_CONST_PROPERY(ONE_MINUS_CONSTANT_ALPHA), + + BINDING_CONST_PROPERY(BLEND_EQUATION), + BINDING_CONST_PROPERY(BLEND_EQUATION_RGB), + BINDING_CONST_PROPERY(BLEND_EQUATION_ALPHA), + BINDING_CONST_PROPERY(BLEND_DST_RGB), + BINDING_CONST_PROPERY(BLEND_SRC_RGB), + BINDING_CONST_PROPERY(BLEND_DST_ALPHA), + BINDING_CONST_PROPERY(BLEND_SRC_ALPHA), + BINDING_CONST_PROPERY(BLEND_COLOR), + BINDING_CONST_PROPERY(ARRAY_BUFFER_BINDING), + BINDING_CONST_PROPERY(ELEMENT_ARRAY_BUFFER_BINDING), + BINDING_CONST_PROPERY(LINE_WIDTH), + BINDING_CONST_PROPERY(ALIASED_POINT_SIZE_RANGE), + BINDING_CONST_PROPERY(ALIASED_LINE_WIDTH_RANGE), + BINDING_CONST_PROPERY(CULL_FACE_MODE), + BINDING_CONST_PROPERY(FRONT_FACE), + BINDING_CONST_PROPERY(DEPTH_RANGE), + BINDING_CONST_PROPERY(DEPTH_WRITEMASK), + BINDING_CONST_PROPERY(DEPTH_CLEAR_VALUE), + BINDING_CONST_PROPERY(DEPTH_FUNC), + BINDING_CONST_PROPERY(STENCIL_CLEAR_VALUE), + BINDING_CONST_PROPERY(STENCIL_FUNC), + BINDING_CONST_PROPERY(STENCIL_FAIL), + BINDING_CONST_PROPERY(STENCIL_PASS_DEPTH_FAIL), + BINDING_CONST_PROPERY(STENCIL_PASS_DEPTH_PASS), + BINDING_CONST_PROPERY(STENCIL_REF), + BINDING_CONST_PROPERY(STENCIL_VALUE_MASK), + BINDING_CONST_PROPERY(STENCIL_WRITEMASK), + BINDING_CONST_PROPERY(STENCIL_BACK_FUNC), + BINDING_CONST_PROPERY(STENCIL_BACK_FAIL), + BINDING_CONST_PROPERY(STENCIL_BACK_PASS_DEPTH_FAIL), + BINDING_CONST_PROPERY(STENCIL_BACK_PASS_DEPTH_PASS), + BINDING_CONST_PROPERY(STENCIL_BACK_REF), + BINDING_CONST_PROPERY(STENCIL_BACK_VALUE_MASK), + BINDING_CONST_PROPERY(STENCIL_BACK_WRITEMASK), + BINDING_CONST_PROPERY(VIEWPORT), + BINDING_CONST_PROPERY(SCISSOR_BOX), + BINDING_CONST_PROPERY(COLOR_CLEAR_VALUE), + BINDING_CONST_PROPERY(COLOR_WRITEMASK), + BINDING_CONST_PROPERY(UNPACK_ALIGNMENT), + BINDING_CONST_PROPERY(PACK_ALIGNMENT), + BINDING_CONST_PROPERY(MAX_TEXTURE_SIZE), + BINDING_CONST_PROPERY(MAX_VIEWPORT_DIMS), + BINDING_CONST_PROPERY(SUBPIXEL_BITS), + BINDING_CONST_PROPERY(RED_BITS), + BINDING_CONST_PROPERY(GREEN_BITS), + BINDING_CONST_PROPERY(BLUE_BITS), + BINDING_CONST_PROPERY(ALPHA_BITS), + BINDING_CONST_PROPERY(DEPTH_BITS), + BINDING_CONST_PROPERY(STENCIL_BITS), + BINDING_CONST_PROPERY(POLYGON_OFFSET_UNITS), + BINDING_CONST_PROPERY(POLYGON_OFFSET_FACTOR), + BINDING_CONST_PROPERY(TEXTURE_BINDING_2D), + BINDING_CONST_PROPERY(SAMPLE_BUFFERS), + BINDING_CONST_PROPERY(SAMPLES), + BINDING_CONST_PROPERY(SAMPLE_COVERAGE_VALUE), + BINDING_CONST_PROPERY(SAMPLE_COVERAGE_INVERT), + BINDING_CONST_PROPERY(COMPRESSED_TEXTURE_FORMATS), + BINDING_CONST_PROPERY(VENDOR), + BINDING_CONST_PROPERY(RENDERER), + BINDING_CONST_PROPERY(VERSION), + BINDING_CONST_PROPERY(IMPLEMENTATION_COLOR_READ_TYPE), + BINDING_CONST_PROPERY(IMPLEMENTATION_COLOR_READ_FORMAT), + + BINDING_CONST_PROPERY(NEVER), + BINDING_CONST_PROPERY(LESS), + BINDING_CONST_PROPERY(EQUAL), + BINDING_CONST_PROPERY(LEQUAL), + BINDING_CONST_PROPERY(GREATER), + BINDING_CONST_PROPERY(NOTEQUAL), + BINDING_CONST_PROPERY(GEQUAL), + BINDING_CONST_PROPERY(ALWAYS), + + BINDING_CONST_PROPERY(KEEP), + BINDING_CONST_PROPERY(REPLACE), + BINDING_CONST_PROPERY(INCR), + BINDING_CONST_PROPERY(DECR), + BINDING_CONST_PROPERY(INVERT), + BINDING_CONST_PROPERY(INCR_WRAP), + BINDING_CONST_PROPERY(DECR_WRAP), + + BINDING_CONST_PROPERY(NEAREST), + BINDING_CONST_PROPERY(LINEAR), + BINDING_CONST_PROPERY(NEAREST_MIPMAP_NEAREST), + BINDING_CONST_PROPERY(LINEAR_MIPMAP_NEAREST), + BINDING_CONST_PROPERY(NEAREST_MIPMAP_LINEAR), + BINDING_CONST_PROPERY(LINEAR_MIPMAP_LINEAR), + BINDING_CONST_PROPERY(TEXTURE_MAG_FILTER), + BINDING_CONST_PROPERY(TEXTURE_MIN_FILTER), + BINDING_CONST_PROPERY(TEXTURE_WRAP_S), + BINDING_CONST_PROPERY(TEXTURE_WRAP_T), + BINDING_CONST_PROPERY(TEXTURE_2D), + BINDING_CONST_PROPERY(TEXTURE), + BINDING_CONST_PROPERY(TEXTURE_CUBE_MAP), + BINDING_CONST_PROPERY(TEXTURE_BINDING_CUBE_MAP), + BINDING_CONST_PROPERY(TEXTURE_CUBE_MAP_POSITIVE_X), + BINDING_CONST_PROPERY(TEXTURE_CUBE_MAP_NEGATIVE_X), + BINDING_CONST_PROPERY(TEXTURE_CUBE_MAP_POSITIVE_Y), + BINDING_CONST_PROPERY(TEXTURE_CUBE_MAP_NEGATIVE_Y), + BINDING_CONST_PROPERY(TEXTURE_CUBE_MAP_POSITIVE_Z), + BINDING_CONST_PROPERY(TEXTURE_CUBE_MAP_NEGATIVE_Z), + BINDING_CONST_PROPERY(MAX_CUBE_MAP_TEXTURE_SIZE), + BINDING_CONST_PROPERY(TEXTURE0), + BINDING_CONST_PROPERY(TEXTURE1), + BINDING_CONST_PROPERY(TEXTURE2), + BINDING_CONST_PROPERY(TEXTURE3), + BINDING_CONST_PROPERY(TEXTURE4), + BINDING_CONST_PROPERY(TEXTURE5), + BINDING_CONST_PROPERY(TEXTURE6), + BINDING_CONST_PROPERY(TEXTURE7), + BINDING_CONST_PROPERY(TEXTURE8), + BINDING_CONST_PROPERY(TEXTURE9), + BINDING_CONST_PROPERY(TEXTURE10), + BINDING_CONST_PROPERY(TEXTURE11), + BINDING_CONST_PROPERY(TEXTURE12), + BINDING_CONST_PROPERY(TEXTURE13), + BINDING_CONST_PROPERY(TEXTURE14), + BINDING_CONST_PROPERY(TEXTURE15), + BINDING_CONST_PROPERY(TEXTURE16), + BINDING_CONST_PROPERY(TEXTURE17), + BINDING_CONST_PROPERY(TEXTURE18), + BINDING_CONST_PROPERY(TEXTURE19), + BINDING_CONST_PROPERY(TEXTURE20), + BINDING_CONST_PROPERY(TEXTURE21), + BINDING_CONST_PROPERY(TEXTURE22), + BINDING_CONST_PROPERY(TEXTURE23), + BINDING_CONST_PROPERY(TEXTURE24), + BINDING_CONST_PROPERY(TEXTURE25), + BINDING_CONST_PROPERY(TEXTURE26), + BINDING_CONST_PROPERY(TEXTURE27), + BINDING_CONST_PROPERY(TEXTURE28), + BINDING_CONST_PROPERY(TEXTURE29), + BINDING_CONST_PROPERY(TEXTURE30), + BINDING_CONST_PROPERY(TEXTURE31), + + BINDING_CONST_PROPERY(ACTIVE_TEXTURE), + BINDING_CONST_PROPERY(REPEAT), + BINDING_CONST_PROPERY(CLAMP_TO_EDGE), + BINDING_CONST_PROPERY(MIRRORED_REPEAT), + + InstanceAccessor("drawBufferWidth", &ContextWebGL::getDrawingBufferWidth, nullptr), + InstanceAccessor("drawBufferHeight", &ContextWebGL::getDrawingBufferHeight, nullptr), + InstanceAccessor("UNPACK_FLIP_Y_WEBGL", &ContextWebGL::getUNPACK_FLIP_Y_WEBGL, nullptr), + InstanceAccessor("UNPACK_PREMULTIPLY_ALPHA_WEBGL", &ContextWebGL::getUNPACK_PREMULTIPLY_ALPHA_WEBGL, nullptr), + }); + constructor = Napi::Persistent(func); + } + ContextWebGL::ContextWebGL(const Napi::CallbackInfo &info) : Napi::ObjectWrap(info) + { + mUnpackFlipYWebGL = false; + mUnpackPremultiplyAlphaWebGL = false; + } + + ContextWebGL::~ContextWebGL() + { + this->mRenderContext = nullptr; + } + + Napi::Object ContextWebGL::NewInstance(Napi::Env env) + { + Napi::Object obj = constructor.New({}); + obj.Set("name", Napi::String::New(env, "contextwebgl")); + return obj; + } + +DEFINE_VOID_METHOD(clear) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLbitfield mask = info[0].As().Uint32Value(); + GL_CHECK( glClear(mask) ); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(clearColor) +{ + if( !CHECK_PARAM_LEGNTH(4) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLfloat red = info[0].As().FloatValue(); + GLfloat green = info[1].As().FloatValue(); + GLfloat blue = info[2].As().FloatValue(); + GLfloat alpha = info[3].As().FloatValue(); + GL_CHECK( glClearColor(red, green, blue, alpha) ); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(enable) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum cap = info[0].As().Uint32Value(); + GL_CHECK( glEnable(cap) ); + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(createBuffer) +{ + // RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLuint bufferId; + glGenBuffers(1, &bufferId); + // GL_CHECK(glGenBuffers(1, &bufferId)); + Napi::Object obj = WebGLBuffer::NewInstance(info.Env(), Napi::Number::New(info.Env(), bufferId)); + // this->mRenderContext->getCtxWebGL()->AddGLResource(Buffer, bufferId); + // RECORD_TIME_END + return obj; +} + +DEFINE_VOID_METHOD(bindBuffer) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum type = info[0].As().Uint32Value(); + GLuint bufferId; + if (info[1].IsNull() || info[1].IsUndefined()) + { + bufferId = 0; + } + else + { + WebGLBuffer *buffer = Napi::ObjectWrap::Unwrap(info[1].As()); + bufferId = buffer->getId(); + } + GL_CHECK(glBindBuffer(type, bufferId)); + RECORD_TIME_END +} + +/** + *WebGL1 支持多种方式 + * gl.bufferData(target, size, usage); + * gl.bufferData(target, ArrayBuffer? srcData, usage); + * gl.bufferData(target, ArrayBufferView srcData, usage); + **/ +DEFINE_VOID_METHOD(bufferData) +{ + if( !CHECK_PARAM_LEGNTH(3) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum target = info[0].As().Uint32Value(); + GLenum usage = info[2].As().Uint32Value(); + if (info[1].IsTypedArray()) + { + Napi::TypedArray array = info[1].As(); + Napi::Uint8Array buffer = array.As(); + GL_CHECK(glBufferData(target, buffer.ByteLength(), buffer.Data(), usage)); + } + else if (info[1].IsArrayBuffer()) + { + Napi::ArrayBuffer array = info[1].As(); + Napi::Uint8Array buffer = array.As(); + GL_CHECK(glBufferData(target, array.ByteLength(), buffer.Data(), usage)); + } + else if( info[1].IsArray() ) + { + //TODO + } + else if (info[1].IsNumber()) + { + GLuint size = info[1].As().Int32Value(); + GL_CHECK(glBufferData(target, size, NULL, usage)); + } + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(bufferSubData) +{ + if( !CHECK_PARAM_LEGNTH(3) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum target = info[0].As().Uint32Value(); + GLenum offset = info[1].As().Uint32Value(); + if (info[2].IsTypedArray()) + { + Napi::TypedArray array = info[2].As(); + Napi::Uint8Array buffer = array.As(); + GL_CHECK(glBufferSubData(target, offset, buffer.ByteLength(), buffer.Data())); + } + else if (info[2].IsArrayBuffer()) + { + Napi::ArrayBuffer array = info[2].As(); + Napi::Uint8Array buffer = array.As(); + GL_CHECK(glBufferSubData(target, offset, buffer.ByteLength(), buffer.Data())); + } + else if( info[2].IsArray() ) + { + //TODO + } + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(createShader) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return info.Env().Null(); + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + Napi::Env env = info.Env(); + GLenum shaderType = info[0].As().Uint32Value(); + GL_CHECK( GLuint shaderId = glCreateShader(shaderType) ); + Napi::Object obj = WebGLShader::NewInstance(env, Napi::Number::New(env, shaderId)); + RECORD_TIME_END + return obj; +} + +DEFINE_VOID_METHOD(shaderSource) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLShader *shader = Napi::ObjectWrap::Unwrap(info[0].As()); + std::string shaderStr = info[1].As().Utf8Value(); + const char *shaderContent = shaderStr.c_str(); + GLint shaderContentLen = shaderStr.size(); + GLuint shaderId = shader->getId(); + GL_CHECK(glShaderSource(shader->getId(), 1, &shaderContent, &shaderContentLen)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(compileShader) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLShader *shader = Napi::ObjectWrap::Unwrap(info[0].As()); + GL_CHECK(glCompileShader(shader->getId())); + GLint compiled = 0; + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(attachShader) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLProgram *program = Napi::ObjectWrap::Unwrap(info[0].As()); + WebGLShader *shader = Napi::ObjectWrap::Unwrap(info[1].As()); + GL_CHECK(glAttachShader(program->getId(), shader->getId())); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(detachShader) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLProgram *program = Napi::ObjectWrap::Unwrap(info[0].As()); + WebGLShader *shader = Napi::ObjectWrap::Unwrap(info[1].As()); + GL_CHECK(glDetachShader(program->getId(), shader->getId())); + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(createProgram) +{ + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLuint programId = glCreateProgram(); + RECORD_TIME_END + return WebGLProgram::NewInstance(info.Env(), Napi::Number::New(info.Env(), programId)); +} + +DEFINE_VOID_METHOD(linkProgram) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLProgram *program = Napi::ObjectWrap::Unwrap(info[0].As()); + GL_CHECK(glLinkProgram(program->getId())); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(useProgram) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLProgram *program = Napi::ObjectWrap::Unwrap(info[0].As()); + GL_CHECK(glUseProgram(program->getId())); + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(getAttribLocation) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return info.Env().Null(); + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLProgram *program = Napi::ObjectWrap::Unwrap(info[0].As()); + std::string name = info[1].As().Utf8Value(); + GL_CHECK(GLuint pos = glGetAttribLocation(program->getId(), name.c_str())); + RECORD_TIME_END + return Napi::Number::New(info.Env(), pos); +} + +// DEFINE_VOID_METHOD(viewport) +void ContextWebGL::viewport(const Napi::CallbackInfo &info) +{ + if( !CHECK_PARAM_LEGNTH(4) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLint x = info[0].As().Int32Value(); + GLint y = info[1].As().Int32Value(); + GLsizei width = info[2].As().Int32Value(); + GLsizei height = info[3].As().Int32Value(); + int dpi = mRenderContext->getDpi(); + printf("dpi=%d\n", dpi); + GL_CHECK(glViewport(x *dpi, y *dpi, width *dpi, height *dpi)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(drawElements) +{ + if( !CHECK_PARAM_LEGNTH(4) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum mode = info[0].As().Uint32Value(); + GLsizei count = info[1].As().Int32Value(); + GLenum type = info[2].As().Uint32Value(); + GLuint offset = info[3].As().Uint32Value(); + GL_CHECK(glDrawElements(mode, count, type, (GLvoid *)(intptr_t)offset)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(flush) +{ + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK(glFlush()); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(finish) +{ + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK(glFinish()); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(vertexAttribPointer) +{ + if( !CHECK_PARAM_LEGNTH(6) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLuint index = info[0].As().Int32Value(); + GLint size = info[1].As().Int32Value(); + GLenum type = info[2].As().Uint32Value(); + GLboolean isNormalized = info[3].As().Value(); + GLuint stride = info[4].As().Int32Value(); + GLuint offset = info[5].As().Int32Value(); + GL_CHECK(glVertexAttribPointer(index, size, type, isNormalized, stride, (GLvoid *)(intptr_t)offset)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(enableVertexAttribArray) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLuint index = info[0].As().Uint32Value(); + GL_CHECK(glEnableVertexAttribArray(index)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(scissor) +{ + if( !CHECK_PARAM_LEGNTH(4) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLint x = info[0].As().Int32Value(); + GLint y = info[1].As().Int32Value(); + GLsizei width = info[2].As().Int32Value(); + GLsizei height = info[3].As().Int32Value(); + int dpi = mRenderContext->getDpi(); + GL_CHECK(glScissor(x *dpi, y *dpi, width *dpi, height *dpi)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(drawArrays) +{ + if( !CHECK_PARAM_LEGNTH(3) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum mode = info[0].As().Uint32Value(); + GLint first = info[1].As().Int32Value(); + GLint count = info[2].As().Int32Value(); + GL_CHECK(glDrawArrays(mode, first, count)); + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(getShaderParameter) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return info.Env().Null(); + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLShader *shader = Napi::ObjectWrap::Unwrap(info[0].As()); + GLenum pname = info[1].As().Uint32Value(); + GLint ret = 0; + GL_CHECK(glGetShaderiv(shader->getId(), pname, &ret)); + RECORD_TIME_END + return Napi::Number::New(info.Env(), ret); +} + +DEFINE_RETURN_VALUE_METHOD(getShaderInfoLog) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return Napi::String::New(info.Env(), ""); + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLShader *shader = Napi::ObjectWrap::Unwrap(info[0].As()); + GLsizei length; + glGetShaderiv(shader->getId(), GL_INFO_LOG_LENGTH, &length); + if (length <= 0) + { + RECORD_TIME_END + return Napi::String::New(info.Env(), ""); + } + else + { + GLchar *src = new GLchar[length]; + int real_size = 0; + GL_CHECK(glGetShaderInfoLog(shader->getId(), length, &real_size, src)); + RECORD_TIME_END + return Napi::String::New(info.Env(), src); + } +} + +DEFINE_VOID_METHOD(deleteShader) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLShader *shader = Napi::ObjectWrap::Unwrap(info[0].As()); + GL_CHECK(glDeleteShader(shader->getId())); + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(getProgramParameter) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return info.Env().Null(); + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLProgram *program = Napi::ObjectWrap::Unwrap(info[0].As()); + GLenum pname = info[1].As().Uint32Value(); + GLint ret; + GL_CHECK(glGetProgramiv(program->getId(), pname, &ret)); + RECORD_TIME_END + return Napi::Number::New(info.Env(), ret); +} + +DEFINE_VOID_METHOD(deleteProgram) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLProgram *program = Napi::ObjectWrap::Unwrap(info[0].As()); + GL_CHECK(glDeleteProgram(program->getId())); + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(getUniformLocation) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return info.Env().Null(); + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLProgram *program = Napi::ObjectWrap::Unwrap(info[0].As()); + std::string shaderStr = info[1].As().Utf8Value(); + GL_CHECK(GLuint index = glGetUniformLocation(program->getId(), shaderStr.c_str())); + Napi::Object obj = WebGLUniformLocation::NewInstance(info.Env(), index); + RECORD_TIME_END + return obj; +} +DEFINE_VOID_METHOD(uniform1f) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLUniformLocation *location = Napi::ObjectWrap::Unwrap(info[0].As()); + GLfloat v1 = parseFloat(info[1]); + GL_CHECK(glUniform1f(location->getIndex(), v1)); + RECORD_TIME_END +} +DEFINE_VOID_METHOD(uniform2f) +{ + if( !CHECK_PARAM_LEGNTH(3) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLUniformLocation *location = Napi::ObjectWrap::Unwrap(info[0].As()); + GLfloat v1 = parseFloat(info[1]); + GLfloat v2 = parseFloat(info[2]); + GL_CHECK(glUniform2f(location->getIndex(), v1, v2)); + RECORD_TIME_END +} +DEFINE_VOID_METHOD(uniform3f) +{ + if( !CHECK_PARAM_LEGNTH(4) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLUniformLocation *location = Napi::ObjectWrap::Unwrap(info[0].As()); + GLfloat v1 = parseFloat(info[1]); + GLfloat v2 = parseFloat(info[2]); + GLfloat v3 = parseFloat(info[3]); + GL_CHECK(glUniform3f(location->getIndex(), v1, v2, v3)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(uniform4f) +{ + if( !CHECK_PARAM_LEGNTH(5) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLUniformLocation *location = Napi::ObjectWrap::Unwrap(info[0].As()); + GLfloat v1 = parseFloat(info[1]); + GLfloat v2 = parseFloat(info[2]); + GLfloat v3 = parseFloat(info[3]); + GLfloat v4 = parseFloat(info[4]); + GL_CHECK(glUniform4f(location->getIndex(), v1, v2, v3, v4)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(colorMask) +{ + if( !CHECK_PARAM_LEGNTH(4) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLint v1, v2, v3, v4; + v1 = parseInt(info[0]); + v2 = parseInt(info[1]); + v3 = parseInt(info[2]); + v4 = parseInt(info[3]); + GL_CHECK(glColorMask(v1, v2, v3, v4)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(uniform1i) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLUniformLocation *location = Napi::ObjectWrap::Unwrap(info[0].As()); + GLint v1 = info[1].As().Int32Value(); + GL_CHECK(glUniform1i(location->getIndex(), v1)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(uniform2i) +{ + if( !CHECK_PARAM_LEGNTH(3) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLUniformLocation *location = Napi::ObjectWrap::Unwrap(info[0].As()); + GLint v1 = info[1].As().Int32Value(); + GLint v2 = info[2].As().Int32Value(); + GL_CHECK(glUniform2i(location->getIndex(), v1, v2)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(uniform3i) +{ + if( !CHECK_PARAM_LEGNTH(4) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLUniformLocation *location = Napi::ObjectWrap::Unwrap(info[0].As()); + GLint v1 = info[1].As().Int32Value(); + GLint v2 = info[2].As().Int32Value(); + GLint v3 = info[3].As().Int32Value(); + GL_CHECK(glUniform3i(location->getIndex(), v1, v2, v3)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(uniform4i) +{ + if( !CHECK_PARAM_LEGNTH(5) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLUniformLocation *location = Napi::ObjectWrap::Unwrap(info[0].As()); + GLint v1 = info[1].As().Int32Value(); + GLint v2 = info[2].As().Int32Value(); + GLint v3 = info[3].As().Int32Value(); + GLint v4 = info[4].As().Int32Value(); + GL_CHECK(glUniform4i(location->getIndex(), v1, v2, v3, v4)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(uniform1fv) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK( parseTypeArrayAndCallUniformFloatFunc(info, glUniform1fv) ); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(uniform2fv) +{ + if( !CHECK_PARAM_LEGNTH(3) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK(parseTypeArrayAndCallUniformFloatFunc(info, glUniform2fv)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(uniform3fv) +{ + if( !CHECK_PARAM_LEGNTH(4) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK(parseTypeArrayAndCallUniformFloatFunc(info, glUniform3fv)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(uniform4fv) +{ + if( !CHECK_PARAM_LEGNTH(5) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK(parseTypeArrayAndCallUniformFloatFunc(info, glUniform4fv)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(uniform1iv) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK(parseTypeArrayAndCallUniformIntFunc(info, glUniform1iv)); + RECORD_TIME_END +} +DEFINE_VOID_METHOD(uniform2iv) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK(parseTypeArrayAndCallUniformIntFunc(info, glUniform2iv)); + RECORD_TIME_END +} +DEFINE_VOID_METHOD(uniform3iv) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK(parseTypeArrayAndCallUniformIntFunc(info, glUniform3iv)); + RECORD_TIME_END +} +DEFINE_VOID_METHOD(uniform4iv) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK(parseTypeArrayAndCallUniformIntFunc(info, glUniform4iv)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(uniformMatrix2fv) +{ + if( !CHECK_PARAM_LEGNTH(3) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK(parseTypeArrayAndCallUniformMatrixFunc(info, 4, glUniformMatrix2fv)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(uniformMatrix3fv) +{ + if( !CHECK_PARAM_LEGNTH(3) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK(parseTypeArrayAndCallUniformMatrixFunc(info, 9, glUniformMatrix3fv)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(uniformMatrix4fv) +{ + if( !CHECK_PARAM_LEGNTH(3) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK(parseTypeArrayAndCallUniformMatrixFunc(info, 16, glUniformMatrix4fv)); + RECORD_TIME_END +} + +void ContextWebGL::parseTypeArrayAndCallUniformFloatFunc(const Napi::CallbackInfo &info, glUniformFloatPtr func) +{ + WebGLUniformLocation *location = Napi::ObjectWrap::Unwrap(info[0].As()); + if (info[1].IsTypedArray()) + { + Napi::TypedArray array = info[1].As(); + Napi::Float32Array buffer = array.As(); + func(location->getIndex(), buffer.ElementLength(), buffer.Data()); + } + else if (info[1].IsArrayBuffer()) + { + Napi::ArrayBuffer array = info[1].As(); + Napi::Float32Array buffer = array.As(); + func(location->getIndex(), buffer.ElementLength(), buffer.Data()); + } + else if( info[1].IsArray() ) + { + Napi::Array array = info[2].As(); + float floatArray[array.Length()]; + for (size_t i = 0; i < array.Length(); i++) + { + floatArray[i] = array.Get(i).ToNumber(); + } + func(location->getIndex(), array.Length(), floatArray); + } +} + +void ContextWebGL::parseTypeArrayAndCallUniformIntFunc(const Napi::CallbackInfo &info, glUniformIntPtr func) +{ + WebGLUniformLocation *location = Napi::ObjectWrap::Unwrap(info[0].As()); + if (info[1].IsTypedArray()) + { + Napi::TypedArray array = info[1].As(); + Napi::Int32Array buffer = array.As(); + func(location->getIndex(), buffer.ElementLength(), buffer.Data()); + } + else if (info[1].IsArrayBuffer()) + { + Napi::ArrayBuffer array = info[1].As(); + Napi::Int32Array buffer = array.As(); + func(location->getIndex(), buffer.ElementLength(), buffer.Data()); + } + else if( info[1].IsArray() ) + { + Napi::Array array = info[2].As(); + int intArray[array.Length()]; + for (size_t i = 0; i < array.Length(); i++) + { + intArray[i] = array.Get(i).ToNumber(); + } + func(location->getIndex(), array.Length(), intArray); + } +} + +void ContextWebGL::parseTypeArrayAndCallUniformMatrixFunc(const Napi::CallbackInfo &info, int size, glUniformMatrixPtr func) +{ + WebGLUniformLocation *location = Napi::ObjectWrap::Unwrap(info[0].As()); + GLboolean transpose = info[1].As().Value(); + + if (info[2].IsTypedArray()) + { /* constant-expression */ + Napi::TypedArray array = info[2].As(); + Napi::Float32Array buffer = array.As(); + func(location->getIndex(), buffer.ElementLength()/size, transpose, buffer.Data()); + } + else if (info[2].IsArrayBuffer()) + { + Napi::ArrayBuffer array = info[2].As(); + Napi::Float32Array buffer = array.As(); + func(location->getIndex(), buffer.ElementLength()/size, transpose, buffer.Data()); + } + else if( info[2].IsArray() ) + { + Napi::Array array = info[2].As(); + float floatArray[array.Length()]; + for (size_t i = 0; i < array.Length(); i++) + { + floatArray[i] = array.Get(i).ToNumber(); + } + + func(location->getIndex(), array.Length()/size, transpose, floatArray); + } +} + +void ContextWebGL::parseTypeArrayAndCallVertexFunc(const Napi::CallbackInfo &info, glVeterxFloatPtr func) +{ + GLuint location = info[0].As().Uint32Value(); + if (info[1].IsTypedArray()) + { + Napi::TypedArray array = info[1].As(); + Napi::Float32Array buffer = array.As(); + func(location, buffer.Data()); + } + else if (info[1].IsArrayBuffer()) + { + Napi::ArrayBuffer array = info[1].As(); + Napi::Float32Array buffer = array.As(); + func(location, buffer.Data()); + } +} + +DEFINE_VOID_METHOD(vertexAttrib1f) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLuint location = info[0].As().Uint32Value(); + GLfloat v1 = info[1].As().FloatValue(); + GL_CHECK(glVertexAttrib1f(location, v1)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(vertexAttrib2f) +{ + if( !CHECK_PARAM_LEGNTH(3) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLuint location = info[0].As().Uint32Value(); + GLfloat v1 = info[1].As().FloatValue(); + GLfloat v2 = info[2].As().FloatValue(); + GL_CHECK(glVertexAttrib2f(location, v1, v2)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(vertexAttrib3f) +{ + if( !CHECK_PARAM_LEGNTH(4) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLuint location = info[0].As().Uint32Value(); + GLfloat v1 = info[1].As().FloatValue(); + GLfloat v2 = info[2].As().FloatValue(); + GLfloat v3 = info[3].As().FloatValue(); + GL_CHECK(glVertexAttrib3f(location, v1, v2, v3)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(vertexAttrib4f) +{ + if( !CHECK_PARAM_LEGNTH(5) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLuint location = info[0].As().Uint32Value(); + GLfloat v1 = info[1].As().FloatValue(); + GLfloat v2 = info[2].As().FloatValue(); + GLfloat v3 = info[3].As().FloatValue(); + GLfloat v4 = info[4].As().FloatValue(); + GL_CHECK(glVertexAttrib4f(location, v1, v2, v3, v4)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(vertexAttrib1fv) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK(parseTypeArrayAndCallVertexFunc(info, glVertexAttrib1fv)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(vertexAttrib2fv) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK(parseTypeArrayAndCallVertexFunc(info, glVertexAttrib2fv)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(vertexAttrib3fv) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK(parseTypeArrayAndCallVertexFunc(info, glVertexAttrib3fv)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(vertexAttrib4fv) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GL_CHECK(parseTypeArrayAndCallVertexFunc(info, glVertexAttrib4fv)); + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(createTexture) +{ + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLuint textureId; + GL_CHECK(glGenTextures(1, &textureId)); + Napi::Object obj = WebGLTexture::NewInstance(info.Env(), Napi::Number::New(info.Env(), textureId)); + RECORD_TIME_END + return obj; +} + +DEFINE_VOID_METHOD(bindTexture) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum type = info[0].As().Uint32Value(); + GLuint textureId = 0; + if (info[1].IsNull() || info[0].IsUndefined()) + { + } + else + { + WebGLTexture *texture = Napi::ObjectWrap::Unwrap(info[1].As()); + textureId = texture->getId(); + } + GL_CHECK(glBindTexture(type, textureId)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(pixelStorei) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + GLenum pname = info[0].As().Uint32Value(); + GLuint param = parseUInt(info[1]); + switch (pname) + { + case GL_UNPACK_FLIP_Y_WEBGL: + mUnpackFlipYWebGL = param; + break; + + case GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL: + mUnpackPremultiplyAlphaWebGL = param; + break; + + case GL_UNPACK_COLORSPACE_CONVERSION_WEBGL: + printf("Unsupport GL_UNPACK_COLORSPACE_CONVERSION_WEBGL"); + break; + + default: + EGL_MAKE_CURRENT + GL_CHECK(glPixelStorei(pname, param)); + break; + } + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(texParameteri) +{ + if( !CHECK_PARAM_LEGNTH(3) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum target = info[0].As().Uint32Value(); + GLenum pname = info[1].As().Uint32Value(); + GLenum param = info[2].As().Uint32Value(); + GL_CHECK(glTexParameteri(target, pname, param)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(texParameterf) +{ + if( !CHECK_PARAM_LEGNTH(3) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLfloat target = info[0].As().FloatValue(); + GLfloat pname = info[1].As().FloatValue(); + GLfloat param = info[2].As().FloatValue(); + GL_CHECK(glTexParameterf(target, pname, param)); + RECORD_TIME_END +} +// support: +//gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); +DEFINE_VOID_METHOD(texImage2D) +{ + if( !CHECK_PARAM_LEGNTH(6) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + if (info.Length() == 6) + { + GLenum target = info[0].As().Uint32Value(); + GLuint level = info[1].As().Uint32Value(); + GLint internalFormat = info[2].As().Uint32Value(); + GLint format = info[3].As().Uint32Value(); + GLint type = info[4].As().Int32Value(); + GLint border = 0; + if (info[5].IsNull() || info[5].IsUndefined()) + { + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + GLint width = 0; + GLint height = 0; + GL_CHECK(glTexImage2D(target, level, internalFormat, width, height, border, format, type, nullptr)); + } + else if (info[5].IsObject()) + { + Napi::Object object = info[5].As(); + Napi::Value name = object.Get("name"); + std::string namePropetry = name.As().Utf8Value(); + //todo canvas + if (namePropetry == "image") + { + Image *image = Napi::ObjectWrap::Unwrap(info[5].As()); + + //一次处理 1 个字节 + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + GL_CHECK(glTexImage2D(target, level, internalFormat,image->getWidth(),image->getHeight(), + border, format, type, &image->getPixels()[0])); + } + else + { + + } + } + } + else if( info.Length() == 9 ) + { + //TODO 9个参数 + } + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(stencilFunc) +{ + if( !CHECK_PARAM_LEGNTH(3) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum func = info[0].As().Uint32Value(); + GLint ref = info[1].As().Int32Value(); + GLuint mask = info[2].As().Uint32Value(); + GL_CHECK(glStencilFunc(func, ref, mask)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(stencilOp) +{ + if( !CHECK_PARAM_LEGNTH(3) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum fail = info[0].As().Uint32Value(); + GLenum zfail = info[1].As().Uint32Value(); + GLenum zpass = info[2].As().Uint32Value(); + GL_CHECK(glStencilOp(fail, zfail, zpass)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(activeTexture) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum texture = info[0].As().Uint32Value(); + GL_CHECK(glActiveTexture(texture)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(stencilMask) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLint mask = info[0].As().Uint32Value(); + GL_CHECK(glStencilMask(mask)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(frontFace) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum mode = info[0].As().Uint32Value(); + GL_CHECK(glFrontFace(mode)); + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(createFrameBuffer) +{ + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLuint frameBufferId; + GL_CHECK(glGenFramebuffers(1, &frameBufferId)); + Napi::Object obj = WebGLFrameBuffer::NewInstance(info.Env(), Napi::Number::New(info.Env(), frameBufferId)); + RECORD_TIME_END + return obj; +} + +DEFINE_VOID_METHOD(bindFramebuffer) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum target = info[0].As().Uint32Value(); + GLuint frameBufferId = 0; + if (info[1].IsNull() || info[1].IsUndefined()) + { + } + else + { + WebGLFrameBuffer *buffer = Napi::ObjectWrap::Unwrap(info[1].As()); + frameBufferId = buffer->getId(); + } + GL_CHECK(glBindFramebuffer(target, frameBufferId)); + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(getShaderSource) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return info.Env().Null(); + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLShader *shader = Napi::ObjectWrap::Unwrap(info[0].As()); + GLsizei length; + glGetShaderiv(shader->getId(), GL_SHADER_SOURCE_LENGTH, &length); + GLchar *src = new GLchar[length]; + GL_CHECK(glGetShaderSource(shader->getId(), length, nullptr, src)); + RECORD_TIME_END + return Napi::String::New(info.Env(), src); +} + +DEFINE_RETURN_VALUE_METHOD(checkFramebufferStatus) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return info.Env().Null(); + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum target = info[0].As().Uint32Value(); + GLenum status = glCheckFramebufferStatus(target); + RECORD_TIME_END + return Napi::Number::New(info.Env(), status); +} + +DEFINE_RETURN_VALUE_METHOD(isFramebuffer) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return info.Env().Null(); + + bool isFrameBuffer = false; + if( info[0].IsObject() ) + { + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + + WebGLFrameBuffer *buffer = Napi::ObjectWrap::Unwrap(info[1].As()); + GLuint frameBufferId = buffer->getId(); + GL_CHECK(isFrameBuffer = glIsFramebuffer(frameBufferId)); + RECORD_TIME_END + } + return Napi::Number::New(info.Env(), glIsFramebuffer(isFrameBuffer)); +} + +DEFINE_VOID_METHOD(framebufferRenderbuffer) +{ + if( !CHECK_PARAM_LEGNTH(4) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum target = info[0].As().Uint32Value(); + GLenum attachment = info[1].As().Uint32Value(); + GLenum renderBufferTarget = info[2].As().Uint32Value(); + WebGLRenderBuffer *renderBuffer = Napi::ObjectWrap::Unwrap(info[3].As()); + GL_CHECK(glFramebufferRenderbuffer(target, attachment, renderBufferTarget, renderBuffer->getId())); + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(createRenderBuffer) +{ + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLuint renderBufferId; + glGenRenderbuffers(1, &renderBufferId); + Napi::Object obj = WebGLFrameBuffer::NewInstance(info.Env(), Napi::Number::New(info.Env(), renderBufferId)); + RECORD_TIME_END + return obj; +} + +DEFINE_VOID_METHOD(renderbufferStorage) +{ + if( !CHECK_PARAM_LEGNTH(4) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum target = info[0].As().Uint32Value(); + GLenum format = info[1].As().Uint32Value(); + GLsizei width = info[2].As().Int32Value(); + GLsizei height = info[3].As().Int32Value(); + GL_CHECK(glRenderbufferStorage(target, format, width, height)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(deleteBuffer) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLBuffer *buffer = Napi::ObjectWrap::Unwrap(info[0].As()); + GLuint id = buffer->getId(); + GL_CHECK(glDeleteBuffers(1, &id)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(deleteTexture) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLTexture *texture = Napi::ObjectWrap::Unwrap(info[0].As()); + GLuint id = texture->getId(); + GL_CHECK(glDeleteTextures(1, &id)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(deleteFrameBuffer) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLFrameBuffer *frameBuffer = Napi::ObjectWrap::Unwrap(info[0].As()); + GLuint id = frameBuffer->getId(); + GL_CHECK(glDeleteTextures(1, &id)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(deleteRenderBuffer) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLRenderBuffer *renderBuffer = Napi::ObjectWrap::Unwrap(info[0].As()); + GLuint id = renderBuffer->getId(); + GL_CHECK(glDeleteTextures(1, &id)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(framebufferTexture2D) +{ + if( !CHECK_PARAM_LEGNTH(5) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum target = info[0].As().Uint32Value(); + GLenum attachment = info[1].As().Uint32Value(); + GLenum textarget = info[2].As().Uint32Value(); + WebGLTexture *texture = Napi::ObjectWrap::Unwrap(info[3].As()); + GLint level = info[4].As().Int32Value(); + GL_CHECK(glFramebufferTexture2D(target, attachment, textarget, texture->getId(), level)); + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(getBufferParameter) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return info.Env().Null(); + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLuint target = info[0].As().Uint32Value(); + GLuint pname = info[1].As().Uint32Value(); + GLint result; + GL_CHECK(glGetBufferParameteriv(target, pname, &result)); + RECORD_TIME_END + return Napi::Number::New(info.Env(), result); +} + +DEFINE_RETURN_VALUE_METHOD(isBuffer) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return Napi::Boolean::New(info.Env(), false); + + bool ret = false; + if( info[0].IsObject() ) + { + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLBuffer *buffer = Napi::ObjectWrap::Unwrap(info[0].As()); + GL_CHECK(ret = glIsBuffer(buffer->getId())); + RECORD_TIME_END + } + return Napi::Boolean::New(info.Env(), ret); +} + +DEFINE_RETURN_VALUE_METHOD(isShader) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return Napi::Boolean::New(info.Env(), false); + + bool ret = false; + if( info[0].IsObject() ) + { + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLShader *shader = Napi::ObjectWrap::Unwrap(info[0].As()); + GL_CHECK(ret = glIsShader(shader->getId())); + RECORD_TIME_END + } + return Napi::Boolean::New(info.Env(), ret); +} + +DEFINE_RETURN_VALUE_METHOD(isRenderBuffer) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return Napi::Boolean::New(info.Env(), false); + + bool ret = false; + if( info[0].IsObject() ) + { + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLRenderBuffer *renderBuffer = Napi::ObjectWrap::Unwrap(info[0].As()); + GL_CHECK(ret = glIsRenderbuffer(renderBuffer->getId())); + RECORD_TIME_END + } + return Napi::Boolean::New(info.Env(), ret); +} + +DEFINE_RETURN_VALUE_METHOD(isTexture) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return Napi::Boolean::New(info.Env(), false); + + bool ret = false; + if( info[0].IsObject() ) + { + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLTexture *texture = Napi::ObjectWrap::Unwrap(info[0].As()); + GL_CHECK(ret = glIsTexture(texture->getId())); + RECORD_TIME_END + } + return Napi::Boolean::New(info.Env(), ret); +} + +DEFINE_RETURN_VALUE_METHOD(isProgram) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return Napi::Boolean::New(info.Env(), false); + + bool ret = false; + if( info[0].IsObject() ) + { + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLProgram *program = Napi::ObjectWrap::Unwrap(info[0].As()); + GL_CHECK(ret = glIsProgram(program->getId())); + RECORD_TIME_END + } + return Napi::Boolean::New(info.Env(), ret); +} + +DEFINE_VOID_METHOD(clearDepth) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLfloat depth = info[0].As().FloatValue(); + GL_CHECK(glClearDepthf(depth)); + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(getTexParameter) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return info.Env().Null(); + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum target = info[0].As().Uint32Value(); + GLenum pname = info[1].As().Uint32Value(); + GLint result; + GL_CHECK(glGetTexParameteriv(target, pname, &result)); + RECORD_TIME_END + return Napi::Number::New(info.Env(), result); +} + +DEFINE_RETURN_VALUE_METHOD(getFramebufferAttachmentParameter) +{ + //TODO +// !CHECK_PARAM_LEGNTH(2) +// GLenum target = info[0].As().Uint32Value(); +// GLenum pname = info[1].As().Uint32Value(); +// GLint result; +// glGetTexParameteriv(target, pname, &result); +// RECORD_TIME_END +// return Napi::Number::New(info.Env(), result); +} + +DEFINE_VOID_METHOD(stencilFuncSeparate) +{ + if( !CHECK_PARAM_LEGNTH(4) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum face = info[0].As().Uint32Value(); + GLenum sfail = info[1].As().Uint32Value(); + GLenum dpfail = info[2].As().Uint32Value(); + GLenum dpass = info[3].As().Uint32Value(); + GL_CHECK(glStencilFuncSeparate(face, sfail, dpfail, dpass)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(stencilMaskSeparate) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum face = info[0].As().Uint32Value(); + GLuint mask = info[1].As().Uint32Value(); + GL_CHECK(glStencilMaskSeparate(face, mask)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(stencilOpSeparate) +{ + if( !CHECK_PARAM_LEGNTH(4) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum face = info[0].As().Uint32Value(); + GLenum sfail = info[1].As().Uint32Value(); + GLenum dpfail = info[2].As().Uint32Value(); + GLenum dpass = info[3].As().Uint32Value(); + GL_CHECK(glStencilOpSeparate(face, sfail, dpfail, dpass)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(clearStencil) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLint s = info[0].As().Int32Value(); + GL_CHECK(glClearStencil(s)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(validateProgram) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLProgram *program = Napi::ObjectWrap::Unwrap(info[0].As()); + GL_CHECK(glValidateProgram(program->getId())); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(depthFunc) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum func = info[0].As().Uint32Value(); + GL_CHECK(glDepthMask(func)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(depthMask) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLboolean flag = info[0].As().Value(); + GL_CHECK(glDepthMask(flag)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(disable) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum cap = info[0].As().Uint32Value(); + GL_CHECK(glDisable(cap)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(blendColor) +{ + if( !CHECK_PARAM_LEGNTH(4) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLclampf red = info[0].As().DoubleValue(); + GLclampf green = info[1].As().DoubleValue(); + GLclampf blue = info[2].As().DoubleValue(); + GLclampf alpha = info[3].As().DoubleValue(); + GL_CHECK(glBlendColor(red, green, blue, alpha)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(blendFunc) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum sfactor = info[0].As().Uint32Value(); + GLenum dfactor = info[1].As().Uint32Value(); + GL_CHECK(glBlendFunc(sfactor, dfactor)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(blendFuncSeparate) +{ + if( !CHECK_PARAM_LEGNTH(4) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum one = info[0].As().Uint32Value(); + GLenum two = info[1].As().Uint32Value(); + GLenum three = info[2].As().Uint32Value(); + GLenum four = info[3].As().Uint32Value(); + GL_CHECK(glBlendFuncSeparate(one, two, three, four)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(blendEquation) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum one = info[0].As().Uint32Value(); + GLenum two = info[1].As().Uint32Value(); + GL_CHECK(glBlendEquationSeparate(one, two)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(blendEquationSeparate) +{ + if( !CHECK_PARAM_LEGNTH(4) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum one = info[0].As().Uint32Value(); + GLenum two = info[1].As().Uint32Value(); + GLenum three = info[2].As().Uint32Value(); + GLenum four = info[4].As().Uint32Value(); + GL_CHECK(glBlendFuncSeparate(one, two, three, four)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(cullFace) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum mode = info[0].As().Uint32Value(); + GL_CHECK(glCullFace(mode)); + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(getError) +{ + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum err= glGetError(); + RECORD_TIME_END + return Napi::Number::New(info.Env(), err); + +} + +DEFINE_VOID_METHOD(bindAttribLocation) +{ + if( !CHECK_PARAM_LEGNTH(3) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + + WebGLProgram *program = Napi::ObjectWrap::Unwrap(info[0].As()); + GLuint index = info[1].As().Uint32Value(); + std::string name = info[2].As().Utf8Value(); + GL_CHECK(glBindAttribLocation(program->getId(), index, name.c_str())); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(polygonOffset) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLfloat factor = info[0].As().FloatValue(); + GLfloat untis = info[1].As().FloatValue(); + GL_CHECK(glPolygonOffset(factor, untis)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(lineWidth) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLfloat width = info[0].As().FloatValue(); + GL_CHECK(glLineWidth(width)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(sampleCoverage) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLfloat value = info[0].As().FloatValue(); + GLboolean invert = info[1].As().Value(); + GL_CHECK(glSampleCoverage(value, invert)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(hint) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum target = info[0].As().Uint32Value(); + GLenum mode = info[1].As().Uint32Value(); + GL_CHECK(glHint(target, mode)); + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(isEnabled) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return Napi::Boolean::New(info.Env(), false); + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum cap = info[0].As().Uint32Value(); + GL_CHECK(GLboolean ret = glIsEnabled(cap)); + RECORD_TIME_END + return Napi::Boolean::New(info.Env(), ret); +} + +DEFINE_VOID_METHOD(readPixels) +{ + if( !CHECK_PARAM_LEGNTH(7) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLint x = info[0].As().Int32Value(); + GLint y = info[1].As().Int32Value(); + GLsizei width = info[2].As().Int32Value(); + GLsizei height = info[3].As().Int32Value(); + GLenum format = info[4].As().Uint32Value(); + GLenum type = info[5].As().Uint32Value(); + void *pixels = nullptr; + if (info[6].IsTypedArray()) + { + Napi::TypedArray array = info[1].As(); + Napi::Uint8Array buffer = array.As(); + pixels = buffer.Data(); + } + else if (info[6].IsArrayBuffer()) + { + Napi::ArrayBuffer array = info[1].As(); + Napi::Uint8Array buffer = array.As(); + pixels = buffer.Data(); + } + else + { + //TODO IsArray + } + GL_CHECK(glReadPixels(x, y, width, height, format, type, pixels)); + RECORD_TIME_END +} + +DEFINE_VOID_METHOD(depthRange) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLfloat near = info[0].As().FloatValue(); + GLfloat far = info[1].As().FloatValue(); + GL_CHECK(glDepthRange(near, far)); + RECORD_TIME_END + } + +DEFINE_VOID_METHOD(generateMipmap) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLenum target = info[0].As().Uint32Value(); + GL_CHECK(glGenerateMipmap(target)); + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(getAttachedShaders) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return info.Env().Null(); + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLProgram *program = Napi::ObjectWrap::Unwrap(info[0].As()); + int maxCount = 32; + int shaderCount = 0; + GLuint shaders[maxCount]; + GL_CHECK(glGetAttachedShaders(program->getId(), maxCount, &shaderCount, shaders)); + Napi::Array arr = Napi::Array::New(info.Env()); + for (int i = 0; i < shaderCount; i++) + { + Napi::Object shader = WebGLShader::NewInstance(info.Env(), Napi::Number::New(info.Env(), shaders[i])); + arr.Set(i, shader); + } + RECORD_TIME_END + return arr; +} + +DEFINE_VOID_METHOD(disableVertexAttribArray) +{ + if( !CHECK_PARAM_LEGNTH(1) ) + return; + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + GLuint index = info[0].As().Uint32Value(); + GL_CHECK(glDisableVertexAttribArray(index)); + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(getActiveAttrib) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return info.Env().Null(); + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLProgram *program = Napi::ObjectWrap::Unwrap(info[0].As()); + GLuint programId = program->getId(); + GLint index = info[1].As().Int32Value(); + GLsizei length; + glGetProgramiv(programId, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &length); + GLchar *buffer = new (std::nothrow) GLchar[length]; + GLint size = 0; + GLenum type = 0; + GL_CHECK(glGetActiveAttrib(programId, index, length, NULL, &size, &type, buffer)); + Napi::Object activeInfoObj = WebGLActiveInfo::NewInstance(info.Env(), size, type, buffer); + RECORD_TIME_END + return activeInfoObj; +} + +DEFINE_RETURN_VALUE_METHOD(getActiveUniform) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return info.Env().Null(); + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + WebGLProgram *program = Napi::ObjectWrap::Unwrap(info[0].As()); + GLuint programId = program->getId(); + GLint index = info[1].As().Int32Value(); + GLsizei length; + glGetProgramiv(programId, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &length); + GLchar *buffer = new (std::nothrow) GLchar[length]; + GLint size = 0; + GLenum type = 0; + GL_CHECK(glGetActiveUniform(programId, index, length, NULL, &size, &type, buffer)); + Napi::Object activeInfoObj = WebGLActiveInfo::NewInstance(info.Env(), size, type, buffer); + RECORD_TIME_END + return activeInfoObj; +} + +DEFINE_RETURN_VALUE_METHOD(getUniform) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return info.Env().Null(); + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + + //TODO + // glGetUniformiv() + RECORD_TIME_END +} + +DEFINE_RETURN_VALUE_METHOD(getVertexAttrib) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return info.Env().Null(); + + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + + GLuint index = info[0].As().Uint32Value(); + GLenum pname = info[1].As().Uint32Value(); + if (pname == GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) + { // WebGLBuffer + GLint params; + GL_CHECK(glGetVertexAttribiv(index, pname, ¶ms)); + return Napi::Number::New(info.Env(), params); + } + else if (pname == GL_VERTEX_ATTRIB_ARRAY_ENABLED || + pname == GL_VERTEX_ATTRIB_ARRAY_NORMALIZED) + { // GLBool + GLint params; + GL_CHECK(glGetVertexAttribiv(index, pname, ¶ms)); + return Napi::Number::New(info.Env(), params); + } + else if (pname == GL_VERTEX_ATTRIB_ARRAY_SIZE || + pname == GL_VERTEX_ATTRIB_ARRAY_STRIDE) + { // GLint + GLint params; + GL_CHECK(glGetVertexAttribiv(index, pname, ¶ms)); + return Napi::Number::New(info.Env(), params); + } + else if (pname == GL_VERTEX_ATTRIB_ARRAY_TYPE) + { // GLEnum + GLint params; + GL_CHECK(glGetVertexAttribiv(index, pname, ¶ms)); + return Napi::Number::New(info.Env(), params); + } + else if (pname == GL_CURRENT_VERTEX_ATTRIB) + { // 4元素 Float32Array + GLfloat *data = new GLfloat[4]; + GL_CHECK(glGetVertexAttribfv(index, pname, data)); + Napi::Array arr = Napi::Array::New(info.Env()); + for (int i = 0; i < 4; i++) + { + arr.Set(i, Napi::Number::New(info.Env(), data[i])); + } + return arr; + } + RECORD_TIME_END +} +DEFINE_RETURN_VALUE_METHOD(getVertexAttribOffset) +{ + if( !CHECK_PARAM_LEGNTH(2) ) + return info.Env().Null(); + + GLuint index = info[0].As().Uint32Value(); + GLenum pname = info[1].As().Uint32Value(); + if (pname == GL_VERTEX_ATTRIB_ARRAY_POINTER) + { + RECORD_TIME_BEGIN + EGL_MAKE_CURRENT + int *p; + GL_CHECK(glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, (void **)&p)); + RECORD_TIME_END + return Napi::Number::New(info.Env(), *p); + } + return Napi::Number::New(info.Env(), 0); +} + +DEFINE_RETURN_VALUE_METHOD(isContextLost) +{ + RECORD_TIME_BEGIN + bool flag = false; + if (!mRenderContext) + { + flag = true; + } + RECORD_TIME_END + return Napi::Boolean::New(info.Env(), flag); +} + +} // namespace NodeBinding \ No newline at end of file diff --git a/node/binding/CanvasRenderingContextWebGL.h b/node/binding/CanvasRenderingContextWebGL.h new file mode 100644 index 00000000..e494b0af --- /dev/null +++ b/node/binding/CanvasRenderingContextWebGL.h @@ -0,0 +1,516 @@ +#ifndef CONTEXTWEBGL_H +#define CONTEXTWEBGL_H +#include +#include "GRenderContext.h" + + +#define GL_UNPACK_FLIP_Y_WEBGL 0x9240 +#define GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL 0x9241 +#define GL_UNPACK_COLORSPACE_CONVERSION_WEBGL 0x9243 + +#define DEFINE_CONST_PROPERY_GET_FUNCTION(propertyName) \ + Napi::Value get##propertyName(const Napi::CallbackInfo &info) \ + { \ + return Napi::Number::New(info.Env(), GL_##propertyName); \ + } + +#define CHECK_PARAM_LEGNTH(length) NodeBinding::checkArgs(info, length) + +#define BINDING_CONST_PROPERY(propertyName) \ + InstanceAccessor(#propertyName, &ContextWebGL::get##propertyName, nullptr) + +#define BINDING_OBJECT_METHOD(methodName) \ + InstanceMethod(#methodName, &ContextWebGL::methodName) + +#define DECLARE_VOID_BINDING_METHOD(methodName) \ + void methodName(const Napi::CallbackInfo &info); + +#define DECLARE_RET_VALUE_BINDING_METHOD(methodName) \ + Napi::Value methodName(const Napi::CallbackInfo &info); + +namespace NodeBinding +{ + typedef void (*glUniformFloatPtr)(GLint location, GLsizei count, const GLfloat *value); + typedef void (*glUniformIntPtr)(GLint location, GLsizei count, const GLint *value); + typedef void (*glUniformMatrixPtr)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + typedef void (*glVeterxFloatPtr)(GLuint index, const GLfloat *value); + class ContextWebGL : public Napi::ObjectWrap + { + public: + static void Init(Napi::Env env); + ContextWebGL(const Napi::CallbackInfo &info); + static Napi::Object NewInstance(Napi::Env env); + virtual ~ContextWebGL(); + void inline setRenderContext(std::shared_ptr renderContext) + { + this->mRenderContext = renderContext; + } + + private: + void clear(const Napi::CallbackInfo &info); + void clearColor(const Napi::CallbackInfo &info); + void enable(const Napi::CallbackInfo &info); + void bindBuffer(const Napi::CallbackInfo &info); + void bufferData(const Napi::CallbackInfo &info); + Napi::Value createBuffer(const Napi::CallbackInfo &info); + Napi::Value createShader(const Napi::CallbackInfo &info); + void shaderSource(const Napi::CallbackInfo &info); + void compileShader(const Napi::CallbackInfo &info); + Napi::Value createProgram(const Napi::CallbackInfo &info); + void attachShader(const Napi::CallbackInfo &info); + void linkProgram(const Napi::CallbackInfo &info); + void useProgram(const Napi::CallbackInfo &info); + Napi::Value getAttribLocation(const Napi::CallbackInfo &info); + void viewport(const Napi::CallbackInfo &info); + void drawElements(const Napi::CallbackInfo &info); + void drawArrays(const Napi::CallbackInfo &info); + void flush(const Napi::CallbackInfo &info); + void finish(const Napi::CallbackInfo &info); + void vertexAttribPointer(const Napi::CallbackInfo &info); + void enableVertexAttribArray(const Napi::CallbackInfo &info); + void scissor(const Napi::CallbackInfo &info); + Napi::Value getShaderParameter(const Napi::CallbackInfo &info); + Napi::Value getShaderInfoLog(const Napi::CallbackInfo &info); + void deleteShader(const Napi::CallbackInfo &info); + Napi::Value getProgramParameter(const Napi::CallbackInfo &info); + void deleteProgram(const Napi::CallbackInfo &info); + Napi::Value getUniformLocation(const Napi::CallbackInfo &info); + DECLARE_VOID_BINDING_METHOD(pixelStorei) + DECLARE_RET_VALUE_BINDING_METHOD(createTexture) + DECLARE_VOID_BINDING_METHOD(bindTexture) + DECLARE_VOID_BINDING_METHOD(uniform1f) + DECLARE_VOID_BINDING_METHOD(uniform2f) + DECLARE_VOID_BINDING_METHOD(texParameteri) + DECLARE_VOID_BINDING_METHOD(texParameterf) + DECLARE_VOID_BINDING_METHOD(texImage2D) + DECLARE_VOID_BINDING_METHOD(stencilFunc) + DECLARE_VOID_BINDING_METHOD(stencilOp) + DECLARE_VOID_BINDING_METHOD(stencilMask) + DECLARE_VOID_BINDING_METHOD(activeTexture) + DECLARE_RET_VALUE_BINDING_METHOD(createFrameBuffer) + DECLARE_VOID_BINDING_METHOD(bindFramebuffer) + DECLARE_RET_VALUE_BINDING_METHOD(checkFramebufferStatus) + DECLARE_RET_VALUE_BINDING_METHOD(isFramebuffer) + DECLARE_VOID_BINDING_METHOD(framebufferRenderbuffer) + DECLARE_VOID_BINDING_METHOD(framebufferTexture2D) + DECLARE_RET_VALUE_BINDING_METHOD(createRenderBuffer) + DECLARE_VOID_BINDING_METHOD(deleteFrameBuffer) + DECLARE_VOID_BINDING_METHOD(deleteRenderBuffer) + DECLARE_VOID_BINDING_METHOD(deleteTexture) + DECLARE_VOID_BINDING_METHOD(deleteBuffer) + DECLARE_RET_VALUE_BINDING_METHOD(isBuffer) + DECLARE_RET_VALUE_BINDING_METHOD(getBufferParameter) + DECLARE_RET_VALUE_BINDING_METHOD(isTexture) + DECLARE_RET_VALUE_BINDING_METHOD(isShader) + DECLARE_RET_VALUE_BINDING_METHOD(isProgram) + DECLARE_RET_VALUE_BINDING_METHOD(isRenderBuffer) + DECLARE_VOID_BINDING_METHOD(renderbufferStorage) + DECLARE_VOID_BINDING_METHOD(clearDepth) + DECLARE_VOID_BINDING_METHOD(clearStencil) + DECLARE_RET_VALUE_BINDING_METHOD(getTexParameter) + DECLARE_RET_VALUE_BINDING_METHOD(getFramebufferAttachmentParameter) + DECLARE_VOID_BINDING_METHOD(stencilFuncSeparate) + DECLARE_VOID_BINDING_METHOD(stencilOpSeparate) + DECLARE_VOID_BINDING_METHOD(stencilMaskSeparate) + DECLARE_VOID_BINDING_METHOD(validateProgram) + DECLARE_VOID_BINDING_METHOD(depthFunc) + DECLARE_VOID_BINDING_METHOD(depthMask) + DECLARE_VOID_BINDING_METHOD(detachShader) + DECLARE_VOID_BINDING_METHOD(disable) + DECLARE_VOID_BINDING_METHOD(blendColor) + DECLARE_VOID_BINDING_METHOD(blendFunc) + DECLARE_VOID_BINDING_METHOD(blendFuncSeparate) + DECLARE_VOID_BINDING_METHOD(blendEquation) + DECLARE_VOID_BINDING_METHOD(blendEquationSeparate) + DECLARE_VOID_BINDING_METHOD(cullFace) + DECLARE_VOID_BINDING_METHOD(polygonOffset) + DECLARE_RET_VALUE_BINDING_METHOD(getError) + DECLARE_VOID_BINDING_METHOD(bindAttribLocation) + DECLARE_VOID_BINDING_METHOD(lineWidth) + DECLARE_VOID_BINDING_METHOD(sampleCoverage) + DECLARE_VOID_BINDING_METHOD(frontFace) + DECLARE_VOID_BINDING_METHOD(hint) + DECLARE_RET_VALUE_BINDING_METHOD(isEnabled) + DECLARE_VOID_BINDING_METHOD(readPixels) + DECLARE_VOID_BINDING_METHOD(depthRange) + DECLARE_VOID_BINDING_METHOD(generateMipmap) + DECLARE_RET_VALUE_BINDING_METHOD(getAttachedShaders) + DECLARE_VOID_BINDING_METHOD(disableVertexAttribArray) + DECLARE_RET_VALUE_BINDING_METHOD(getActiveAttrib) + DECLARE_RET_VALUE_BINDING_METHOD(getActiveUniform) + DECLARE_RET_VALUE_BINDING_METHOD(getUniform) + DECLARE_RET_VALUE_BINDING_METHOD(getVertexAttrib) + DECLARE_RET_VALUE_BINDING_METHOD(getVertexAttribOffset) + DECLARE_RET_VALUE_BINDING_METHOD(isContextLost) + DECLARE_VOID_BINDING_METHOD(bufferSubData) + + void uniform3f(const Napi::CallbackInfo &info); + void uniform4f(const Napi::CallbackInfo &info); + + void uniform1i(const Napi::CallbackInfo &info); + void uniform2i(const Napi::CallbackInfo &info); + void uniform3i(const Napi::CallbackInfo &info); + void uniform4i(const Napi::CallbackInfo &info); + + void uniform1fv(const Napi::CallbackInfo &info); + void uniform2fv(const Napi::CallbackInfo &info); + void uniform3fv(const Napi::CallbackInfo &info); + void uniform4fv(const Napi::CallbackInfo &info); + + void uniform1iv(const Napi::CallbackInfo &info); + void uniform2iv(const Napi::CallbackInfo &info); + void uniform3iv(const Napi::CallbackInfo &info); + void uniform4iv(const Napi::CallbackInfo &info); + + void uniformMatrix2fv(const Napi::CallbackInfo &info); + void uniformMatrix3fv(const Napi::CallbackInfo &info); + void uniformMatrix4fv(const Napi::CallbackInfo &info); + + void vertexAttrib1f(const Napi::CallbackInfo &info); + void vertexAttrib2f(const Napi::CallbackInfo &info); + void vertexAttrib3f(const Napi::CallbackInfo &info); + void vertexAttrib4f(const Napi::CallbackInfo &info); + + void vertexAttrib1fv(const Napi::CallbackInfo &info); + void vertexAttrib2fv(const Napi::CallbackInfo &info); + void vertexAttrib3fv(const Napi::CallbackInfo &info); + void vertexAttrib4fv(const Napi::CallbackInfo &info); + + void colorMask(const Napi::CallbackInfo &info); + Napi::Value getShaderSource(const Napi::CallbackInfo &info); + + void parseTypeArrayAndCallUniformFloatFunc(const Napi::CallbackInfo &info, glUniformFloatPtr func); + void parseTypeArrayAndCallUniformIntFunc(const Napi::CallbackInfo &info, glUniformIntPtr func); + void parseTypeArrayAndCallUniformMatrixFunc(const Napi::CallbackInfo &info, int size, glUniformMatrixPtr func); + void parseTypeArrayAndCallVertexFunc(const Napi::CallbackInfo &info, glVeterxFloatPtr func); + + static Napi::FunctionReference constructor; + + DEFINE_CONST_PROPERY_GET_FUNCTION(LINK_STATUS) + DEFINE_CONST_PROPERY_GET_FUNCTION(COLOR_BUFFER_BIT) + DEFINE_CONST_PROPERY_GET_FUNCTION(DEPTH_BUFFER_BIT) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_BUFFER_BIT) + DEFINE_CONST_PROPERY_GET_FUNCTION(TRIANGLES) + DEFINE_CONST_PROPERY_GET_FUNCTION(POINTS) + DEFINE_CONST_PROPERY_GET_FUNCTION(LINE_STRIP) + DEFINE_CONST_PROPERY_GET_FUNCTION(LINES) + DEFINE_CONST_PROPERY_GET_FUNCTION(LINE_LOOP) + DEFINE_CONST_PROPERY_GET_FUNCTION(TRIANGLE_FAN) + DEFINE_CONST_PROPERY_GET_FUNCTION(TRIANGLE_STRIP) + + DEFINE_CONST_PROPERY_GET_FUNCTION(DEPTH_TEST) + DEFINE_CONST_PROPERY_GET_FUNCTION(SCISSOR_TEST) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_TEST) + + DEFINE_CONST_PROPERY_GET_FUNCTION(COMPILE_STATUS) + DEFINE_CONST_PROPERY_GET_FUNCTION(ARRAY_BUFFER) + DEFINE_CONST_PROPERY_GET_FUNCTION(STATIC_DRAW) + DEFINE_CONST_PROPERY_GET_FUNCTION(ELEMENT_ARRAY_BUFFER) + DEFINE_CONST_PROPERY_GET_FUNCTION(VERTEX_SHADER) + DEFINE_CONST_PROPERY_GET_FUNCTION(FRAGMENT_SHADER) + + DEFINE_CONST_PROPERY_GET_FUNCTION(UNSIGNED_SHORT) + DEFINE_CONST_PROPERY_GET_FUNCTION(FLOAT) + DEFINE_CONST_PROPERY_GET_FUNCTION(BYTE) + DEFINE_CONST_PROPERY_GET_FUNCTION(UNSIGNED_BYTE) + DEFINE_CONST_PROPERY_GET_FUNCTION(SHORT) + DEFINE_CONST_PROPERY_GET_FUNCTION(INT) + DEFINE_CONST_PROPERY_GET_FUNCTION(UNSIGNED_INT) + + DEFINE_CONST_PROPERY_GET_FUNCTION(FALSE) + DEFINE_CONST_PROPERY_GET_FUNCTION(TRUE) + DEFINE_CONST_PROPERY_GET_FUNCTION(ZERO) + DEFINE_CONST_PROPERY_GET_FUNCTION(ONE) + + DEFINE_CONST_PROPERY_GET_FUNCTION(SRC_COLOR) + DEFINE_CONST_PROPERY_GET_FUNCTION(ONE_MINUS_SRC_COLOR) + DEFINE_CONST_PROPERY_GET_FUNCTION(SRC_ALPHA) + DEFINE_CONST_PROPERY_GET_FUNCTION(ONE_MINUS_SRC_ALPHA) + DEFINE_CONST_PROPERY_GET_FUNCTION(DST_ALPHA) + DEFINE_CONST_PROPERY_GET_FUNCTION(ONE_MINUS_DST_ALPHA) + DEFINE_CONST_PROPERY_GET_FUNCTION(DST_COLOR) + DEFINE_CONST_PROPERY_GET_FUNCTION(ONE_MINUS_DST_COLOR) + DEFINE_CONST_PROPERY_GET_FUNCTION(SRC_ALPHA_SATURATE) + DEFINE_CONST_PROPERY_GET_FUNCTION(CONSTANT_COLOR) + DEFINE_CONST_PROPERY_GET_FUNCTION(ONE_MINUS_CONSTANT_COLOR) + DEFINE_CONST_PROPERY_GET_FUNCTION(CONSTANT_ALPHA) + DEFINE_CONST_PROPERY_GET_FUNCTION(ONE_MINUS_CONSTANT_ALPHA) + + DEFINE_CONST_PROPERY_GET_FUNCTION(BLEND_EQUATION) + DEFINE_CONST_PROPERY_GET_FUNCTION(BLEND_EQUATION_RGB) + DEFINE_CONST_PROPERY_GET_FUNCTION(BLEND_EQUATION_ALPHA) + DEFINE_CONST_PROPERY_GET_FUNCTION(BLEND_DST_RGB) + DEFINE_CONST_PROPERY_GET_FUNCTION(BLEND_SRC_RGB) + DEFINE_CONST_PROPERY_GET_FUNCTION(BLEND_DST_ALPHA) + DEFINE_CONST_PROPERY_GET_FUNCTION(BLEND_SRC_ALPHA) + DEFINE_CONST_PROPERY_GET_FUNCTION(BLEND_COLOR) + DEFINE_CONST_PROPERY_GET_FUNCTION(ARRAY_BUFFER_BINDING) + DEFINE_CONST_PROPERY_GET_FUNCTION(ELEMENT_ARRAY_BUFFER_BINDING) + DEFINE_CONST_PROPERY_GET_FUNCTION(LINE_WIDTH) + DEFINE_CONST_PROPERY_GET_FUNCTION(ALIASED_POINT_SIZE_RANGE) + DEFINE_CONST_PROPERY_GET_FUNCTION(ALIASED_LINE_WIDTH_RANGE) + DEFINE_CONST_PROPERY_GET_FUNCTION(CULL_FACE_MODE) + DEFINE_CONST_PROPERY_GET_FUNCTION(FRONT_FACE) + DEFINE_CONST_PROPERY_GET_FUNCTION(DEPTH_RANGE) + DEFINE_CONST_PROPERY_GET_FUNCTION(DEPTH_WRITEMASK) + DEFINE_CONST_PROPERY_GET_FUNCTION(DEPTH_CLEAR_VALUE) + DEFINE_CONST_PROPERY_GET_FUNCTION(DEPTH_FUNC) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_CLEAR_VALUE) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_FUNC) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_FAIL) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_PASS_DEPTH_FAIL) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_PASS_DEPTH_PASS) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_REF) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_VALUE_MASK) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_WRITEMASK) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_BACK_FUNC) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_BACK_FAIL) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_BACK_PASS_DEPTH_FAIL) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_BACK_PASS_DEPTH_PASS) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_BACK_REF) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_BACK_VALUE_MASK) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_BACK_WRITEMASK) + DEFINE_CONST_PROPERY_GET_FUNCTION(VIEWPORT) + DEFINE_CONST_PROPERY_GET_FUNCTION(SCISSOR_BOX) + DEFINE_CONST_PROPERY_GET_FUNCTION(COLOR_CLEAR_VALUE) + DEFINE_CONST_PROPERY_GET_FUNCTION(COLOR_WRITEMASK) + DEFINE_CONST_PROPERY_GET_FUNCTION(UNPACK_ALIGNMENT) + DEFINE_CONST_PROPERY_GET_FUNCTION(PACK_ALIGNMENT) + DEFINE_CONST_PROPERY_GET_FUNCTION(MAX_TEXTURE_SIZE) + DEFINE_CONST_PROPERY_GET_FUNCTION(MAX_VIEWPORT_DIMS) + DEFINE_CONST_PROPERY_GET_FUNCTION(SUBPIXEL_BITS) + DEFINE_CONST_PROPERY_GET_FUNCTION(RED_BITS) + DEFINE_CONST_PROPERY_GET_FUNCTION(GREEN_BITS) + DEFINE_CONST_PROPERY_GET_FUNCTION(BLUE_BITS) + DEFINE_CONST_PROPERY_GET_FUNCTION(ALPHA_BITS) + DEFINE_CONST_PROPERY_GET_FUNCTION(DEPTH_BITS) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_BITS) + DEFINE_CONST_PROPERY_GET_FUNCTION(POLYGON_OFFSET_UNITS) + DEFINE_CONST_PROPERY_GET_FUNCTION(POLYGON_OFFSET_FACTOR) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE_BINDING_2D) + DEFINE_CONST_PROPERY_GET_FUNCTION(SAMPLE_BUFFERS) + DEFINE_CONST_PROPERY_GET_FUNCTION(SAMPLES) + DEFINE_CONST_PROPERY_GET_FUNCTION(SAMPLE_COVERAGE_VALUE) + DEFINE_CONST_PROPERY_GET_FUNCTION(SAMPLE_COVERAGE_INVERT) + DEFINE_CONST_PROPERY_GET_FUNCTION(COMPRESSED_TEXTURE_FORMATS) + DEFINE_CONST_PROPERY_GET_FUNCTION(VENDOR) + DEFINE_CONST_PROPERY_GET_FUNCTION(RENDERER) + DEFINE_CONST_PROPERY_GET_FUNCTION(VERSION) + DEFINE_CONST_PROPERY_GET_FUNCTION(IMPLEMENTATION_COLOR_READ_TYPE) + DEFINE_CONST_PROPERY_GET_FUNCTION(IMPLEMENTATION_COLOR_READ_FORMAT) + + DEFINE_CONST_PROPERY_GET_FUNCTION(NEVER) + DEFINE_CONST_PROPERY_GET_FUNCTION(LESS) + DEFINE_CONST_PROPERY_GET_FUNCTION(EQUAL) + DEFINE_CONST_PROPERY_GET_FUNCTION(LEQUAL) + DEFINE_CONST_PROPERY_GET_FUNCTION(GREATER) + DEFINE_CONST_PROPERY_GET_FUNCTION(NOTEQUAL) + DEFINE_CONST_PROPERY_GET_FUNCTION(GEQUAL) + DEFINE_CONST_PROPERY_GET_FUNCTION(ALWAYS) + + DEFINE_CONST_PROPERY_GET_FUNCTION(CURRENT_VERTEX_ATTRIB) + DEFINE_CONST_PROPERY_GET_FUNCTION(VERTEX_ATTRIB_ARRAY_ENABLED) + DEFINE_CONST_PROPERY_GET_FUNCTION(VERTEX_ATTRIB_ARRAY_SIZE) + DEFINE_CONST_PROPERY_GET_FUNCTION(VERTEX_ATTRIB_ARRAY_STRIDE) + DEFINE_CONST_PROPERY_GET_FUNCTION(VERTEX_ATTRIB_ARRAY_TYPE) + DEFINE_CONST_PROPERY_GET_FUNCTION(VERTEX_ATTRIB_ARRAY_NORMALIZED) + DEFINE_CONST_PROPERY_GET_FUNCTION(VERTEX_ATTRIB_ARRAY_POINTER) + DEFINE_CONST_PROPERY_GET_FUNCTION(VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) + + DEFINE_CONST_PROPERY_GET_FUNCTION(CULL_FACE) + DEFINE_CONST_PROPERY_GET_FUNCTION(FRONT) + DEFINE_CONST_PROPERY_GET_FUNCTION(BACK) + DEFINE_CONST_PROPERY_GET_FUNCTION(FRONT_AND_BACK) + + // Enabling and disabling + DEFINE_CONST_PROPERY_GET_FUNCTION(BLEND) + DEFINE_CONST_PROPERY_GET_FUNCTION(DITHER) + DEFINE_CONST_PROPERY_GET_FUNCTION(POLYGON_OFFSET_FILL) + DEFINE_CONST_PROPERY_GET_FUNCTION(SAMPLE_ALPHA_TO_COVERAGE) + DEFINE_CONST_PROPERY_GET_FUNCTION(SAMPLE_COVERAGE) + + // errors + DEFINE_CONST_PROPERY_GET_FUNCTION(NO_ERROR) + DEFINE_CONST_PROPERY_GET_FUNCTION(INVALID_ENUM) + DEFINE_CONST_PROPERY_GET_FUNCTION(INVALID_VALUE) + DEFINE_CONST_PROPERY_GET_FUNCTION(INVALID_OPERATION) + DEFINE_CONST_PROPERY_GET_FUNCTION(OUT_OF_MEMORY) + // DEFINE_CONST_PROPERY_GET_FUNCTION(CONTEXT_LOST_WEBGL) + + // Front face directions + DEFINE_CONST_PROPERY_GET_FUNCTION(CW) + DEFINE_CONST_PROPERY_GET_FUNCTION(CCW) + + DEFINE_CONST_PROPERY_GET_FUNCTION(DONT_CARE) + DEFINE_CONST_PROPERY_GET_FUNCTION(FASTEST) + DEFINE_CONST_PROPERY_GET_FUNCTION(NICEST) + DEFINE_CONST_PROPERY_GET_FUNCTION(GENERATE_MIPMAP_HINT) + + // Pixel types + // BIND_CONSTANT(UNSIGNED_BYTE, 0x1401) + DEFINE_CONST_PROPERY_GET_FUNCTION(UNSIGNED_SHORT_4_4_4_4) + DEFINE_CONST_PROPERY_GET_FUNCTION(UNSIGNED_SHORT_5_5_5_1) + DEFINE_CONST_PROPERY_GET_FUNCTION(UNSIGNED_SHORT_5_6_5) + + DEFINE_CONST_PROPERY_GET_FUNCTION(FLOAT_VEC2) + DEFINE_CONST_PROPERY_GET_FUNCTION(FLOAT_VEC3) + DEFINE_CONST_PROPERY_GET_FUNCTION(FLOAT_VEC4) + DEFINE_CONST_PROPERY_GET_FUNCTION(INT_VEC2) + DEFINE_CONST_PROPERY_GET_FUNCTION(INT_VEC3) + DEFINE_CONST_PROPERY_GET_FUNCTION(INT_VEC4) + DEFINE_CONST_PROPERY_GET_FUNCTION(BOOL) + DEFINE_CONST_PROPERY_GET_FUNCTION(BOOL_VEC2) + DEFINE_CONST_PROPERY_GET_FUNCTION(BOOL_VEC3) + DEFINE_CONST_PROPERY_GET_FUNCTION(BOOL_VEC4) + DEFINE_CONST_PROPERY_GET_FUNCTION(FLOAT_MAT2) + DEFINE_CONST_PROPERY_GET_FUNCTION(FLOAT_MAT3) + DEFINE_CONST_PROPERY_GET_FUNCTION(FLOAT_MAT4) + DEFINE_CONST_PROPERY_GET_FUNCTION(SAMPLER_2D) + DEFINE_CONST_PROPERY_GET_FUNCTION(SAMPLER_CUBE) + + DEFINE_CONST_PROPERY_GET_FUNCTION(LOW_FLOAT) + DEFINE_CONST_PROPERY_GET_FUNCTION(MEDIUM_FLOAT) + DEFINE_CONST_PROPERY_GET_FUNCTION(HIGH_FLOAT) + DEFINE_CONST_PROPERY_GET_FUNCTION(LOW_INT) + DEFINE_CONST_PROPERY_GET_FUNCTION(MEDIUM_INT) + DEFINE_CONST_PROPERY_GET_FUNCTION(HIGH_INT) + + DEFINE_CONST_PROPERY_GET_FUNCTION(KEEP) + DEFINE_CONST_PROPERY_GET_FUNCTION(REPLACE) + DEFINE_CONST_PROPERY_GET_FUNCTION(INCR) + DEFINE_CONST_PROPERY_GET_FUNCTION(DECR) + DEFINE_CONST_PROPERY_GET_FUNCTION(INVERT) + DEFINE_CONST_PROPERY_GET_FUNCTION(INCR_WRAP) + DEFINE_CONST_PROPERY_GET_FUNCTION(DECR_WRAP) + + DEFINE_CONST_PROPERY_GET_FUNCTION(NEAREST) + DEFINE_CONST_PROPERY_GET_FUNCTION(LINEAR) + DEFINE_CONST_PROPERY_GET_FUNCTION(NEAREST_MIPMAP_NEAREST) + DEFINE_CONST_PROPERY_GET_FUNCTION(LINEAR_MIPMAP_NEAREST) + DEFINE_CONST_PROPERY_GET_FUNCTION(NEAREST_MIPMAP_LINEAR) + DEFINE_CONST_PROPERY_GET_FUNCTION(LINEAR_MIPMAP_LINEAR) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE_MAG_FILTER) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE_MIN_FILTER) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE_WRAP_S) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE_WRAP_T) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE_2D) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE_CUBE_MAP) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE_BINDING_CUBE_MAP) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE_CUBE_MAP_POSITIVE_X) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE_CUBE_MAP_NEGATIVE_X) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE_CUBE_MAP_POSITIVE_Y) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE_CUBE_MAP_NEGATIVE_Y) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE_CUBE_MAP_POSITIVE_Z) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE_CUBE_MAP_NEGATIVE_Z) + DEFINE_CONST_PROPERY_GET_FUNCTION(MAX_CUBE_MAP_TEXTURE_SIZE) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE0) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE1) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE2) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE3) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE4) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE5) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE6) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE7) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE8) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE9) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE10) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE11) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE12) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE13) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE14) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE15) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE16) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE17) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE18) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE19) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE20) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE21) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE22) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE23) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE24) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE25) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE26) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE27) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE28) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE29) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE30) + DEFINE_CONST_PROPERY_GET_FUNCTION(TEXTURE31) + + DEFINE_CONST_PROPERY_GET_FUNCTION(ACTIVE_TEXTURE) + DEFINE_CONST_PROPERY_GET_FUNCTION(REPEAT) + DEFINE_CONST_PROPERY_GET_FUNCTION(CLAMP_TO_EDGE) + DEFINE_CONST_PROPERY_GET_FUNCTION(MIRRORED_REPEAT) + + DEFINE_CONST_PROPERY_GET_FUNCTION(FRAMEBUFFER) + DEFINE_CONST_PROPERY_GET_FUNCTION(RENDERBUFFER) + DEFINE_CONST_PROPERY_GET_FUNCTION(RGBA) + DEFINE_CONST_PROPERY_GET_FUNCTION(RGBA4) + DEFINE_CONST_PROPERY_GET_FUNCTION(DEPTH_COMPONENT) + DEFINE_CONST_PROPERY_GET_FUNCTION(ALPHA) + DEFINE_CONST_PROPERY_GET_FUNCTION(RGB5_A1) + DEFINE_CONST_PROPERY_GET_FUNCTION(RGB565) + DEFINE_CONST_PROPERY_GET_FUNCTION(LUMINANCE) + DEFINE_CONST_PROPERY_GET_FUNCTION(LUMINANCE_ALPHA) + DEFINE_CONST_PROPERY_GET_FUNCTION(DEPTH_COMPONENT16) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_INDEX8) + + DEFINE_CONST_PROPERY_GET_FUNCTION(RENDERBUFFER_WIDTH) + DEFINE_CONST_PROPERY_GET_FUNCTION(RENDERBUFFER_HEIGHT) + DEFINE_CONST_PROPERY_GET_FUNCTION(RENDERBUFFER_INTERNAL_FORMAT) + DEFINE_CONST_PROPERY_GET_FUNCTION(RENDERBUFFER_RED_SIZE) + DEFINE_CONST_PROPERY_GET_FUNCTION(RENDERBUFFER_GREEN_SIZE) + DEFINE_CONST_PROPERY_GET_FUNCTION(RENDERBUFFER_BLUE_SIZE) + DEFINE_CONST_PROPERY_GET_FUNCTION(RENDERBUFFER_ALPHA_SIZE) + DEFINE_CONST_PROPERY_GET_FUNCTION(RENDERBUFFER_DEPTH_SIZE) + DEFINE_CONST_PROPERY_GET_FUNCTION(RENDERBUFFER_STENCIL_SIZE) + DEFINE_CONST_PROPERY_GET_FUNCTION(FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) + DEFINE_CONST_PROPERY_GET_FUNCTION(FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) + DEFINE_CONST_PROPERY_GET_FUNCTION(FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL) + DEFINE_CONST_PROPERY_GET_FUNCTION(FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE) + DEFINE_CONST_PROPERY_GET_FUNCTION(COLOR_ATTACHMENT0) + DEFINE_CONST_PROPERY_GET_FUNCTION(DEPTH_ATTACHMENT) + DEFINE_CONST_PROPERY_GET_FUNCTION(STENCIL_ATTACHMENT) + DEFINE_CONST_PROPERY_GET_FUNCTION(NONE) + DEFINE_CONST_PROPERY_GET_FUNCTION(FRAMEBUFFER_COMPLETE) + DEFINE_CONST_PROPERY_GET_FUNCTION(FRAMEBUFFER_INCOMPLETE_ATTACHMENT) + DEFINE_CONST_PROPERY_GET_FUNCTION(FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) + DEFINE_CONST_PROPERY_GET_FUNCTION(FRAMEBUFFER_INCOMPLETE_DIMENSIONS) + DEFINE_CONST_PROPERY_GET_FUNCTION(FRAMEBUFFER_UNSUPPORTED) + DEFINE_CONST_PROPERY_GET_FUNCTION(FRAMEBUFFER_BINDING) + DEFINE_CONST_PROPERY_GET_FUNCTION(RENDERBUFFER_BINDING) + DEFINE_CONST_PROPERY_GET_FUNCTION(MAX_RENDERBUFFER_SIZE) + DEFINE_CONST_PROPERY_GET_FUNCTION(INVALID_FRAMEBUFFER_OPERATION) + + Napi::Value getUNPACK_FLIP_Y_WEBGL(const Napi::CallbackInfo &info) + { + return Napi::Number::New(info.Env(), GL_UNPACK_FLIP_Y_WEBGL); + } + + Napi::Value getUNPACK_PREMULTIPLY_ALPHA_WEBGL(const Napi::CallbackInfo &info) + { + return Napi::Number::New(info.Env(), GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL); + } + + Napi::Value getUNPACK(const Napi::CallbackInfo &info) + { + return Napi::Number::New(info.Env(), 0x9243); + } + + Napi::Value getDrawingBufferWidth(const Napi::CallbackInfo &info) + { + return Napi::Number::New(info.Env(), this->mRenderContext->getWdith()); + } + + Napi::Value getDrawingBufferHeight(const Napi::CallbackInfo &info) + { + return Napi::Number::New(info.Env(), this->mRenderContext->getHeight()); + } + + protected: + std::shared_ptr mRenderContext = nullptr; + bool mUnpackFlipYWebGL; + bool mUnpackPremultiplyAlphaWebGL; + }; +} // namespace NodeBinding +#endif \ No newline at end of file diff --git a/node/binding/Export.cc b/node/binding/Export.cc index e0d1a0f8..67c9f556 100644 --- a/node/binding/Export.cc +++ b/node/binding/Export.cc @@ -11,6 +11,14 @@ #include "Canvas.h" #include "Image.h" #include "TextMetrics.h" +#include "./webgl/WebGLShader.h" +#include "./webgl/WebGLBuffer.h" +#include "./webgl/WebGLProgram.h" +#include "./webgl/WebGLTexture.h" +#include "./webgl/WebGLFrameBuffer.h" +#include "./webgl/WebGLActiveInfo.h" +#include "./webgl/WebGLUniformLocation.h" +#include "./webgl/WebGLRenderBuffer.h" Napi::Object createCanvas(const Napi::CallbackInfo &info) { @@ -36,10 +44,20 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) NodeBinding::Canvas::Init(env, exports); NodeBinding::Image::Init(env, exports); NodeBinding::Context2D::Init(env); + NodeBinding::ContextWebGL::Init(env); NodeBinding::Gradient::Init(env); NodeBinding::ImageData::Init(env); NodeBinding::TextMetrics::Init(env); NodeBinding::Pattern::Init(env); + //webl reousce binding + NodeBinding::WebGLShader::Init(env); + NodeBinding::WebGLProgram::Init(env); + NodeBinding::WebGLBuffer ::Init(env); + NodeBinding::WebGLTexture::Init(env); + NodeBinding::WebGLFrameBuffer::Init(env); + NodeBinding::WebGLRenderBuffer::Init(env); + NodeBinding::WebGLActiveInfo::Init(env); + NodeBinding::WebGLUniformLocation::Init(env); exports.Set(Napi::String::New(env, "createCanvas"), Napi::Function::New(env, createCanvas)); exports.Set(Napi::String::New(env, "createImage"), diff --git a/node/renderContext/GRenderContext.cc b/node/binding/renderContext/GRenderContext.cc similarity index 79% rename from node/renderContext/GRenderContext.cc rename to node/binding/renderContext/GRenderContext.cc index 13c1cf6c..1c4b6b13 100644 --- a/node/renderContext/GRenderContext.cc +++ b/node/binding/renderContext/GRenderContext.cc @@ -18,21 +18,17 @@ namespace NodeBinding static EGLDisplay g_eglDisplay = EGL_NO_DISPLAY; GRenderContext::GRenderContext(int width, int height) - : mWidth(width), mHeight(height), mRatio(2.0), mEglDisplay(EGL_NO_DISPLAY) + : mWidth(width), mHeight(height), mDpi(2), mEglDisplay(EGL_NO_DISPLAY) { - GCanvasConfig config = {true, false}; - this->mCanvas = std::make_shared("node-gcanvas", config, nullptr); - mCanvasWidth = width * mRatio; - mCanvasHeight = height * mRatio; + mCanvasWidth = width * mDpi; + mCanvasHeight = height * mDpi; } GRenderContext::GRenderContext(int width, int height, int ratio) - : mWidth(width), mHeight(height), mRatio(ratio), mEglDisplay(EGL_NO_DISPLAY) + : mWidth(width), mHeight(height), mDpi(ratio), mEglDisplay(EGL_NO_DISPLAY) { - GCanvasConfig config = {true, true}; - this->mCanvas = std::make_shared("node-gcanvas", config, nullptr); - mCanvasWidth = width * mRatio; - mCanvasHeight = height * mRatio; + mCanvasWidth = width * mDpi; + mCanvasHeight = height * mDpi; } void GRenderContext::initRenderEnviroment() @@ -111,17 +107,28 @@ namespace NodeBinding // end of standard gl context setup // Step 9 - create framebuffer object - this->mFboIdSrc = this->createFBO(mCanvasWidth, mCanvasHeight, &this->mRenderBufferIdSrc, &this->mDepthRenderbufferIdSrc); - this->mFboIdDes = this->createFBO(mWidth, mHeight, &this->mRenderBufferIdDes, &this->mDepthRenderbufferIdDes); - glBindFramebuffer(GL_FRAMEBUFFER, this->mFboIdSrc); - - GLint format = 0, type = 0; - glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &format); - glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &type); - this->initCanvas(); + mFboIdSrc = createFBO(mCanvasWidth, mCanvasHeight, &mRenderBufferIdSrc, &mDepthRenderbufferIdSrc); + mFboIdDes = createFBO(mWidth, mHeight, &mRenderBufferIdDes, &mDepthRenderbufferIdDes); + glBindFramebuffer(GL_FRAMEBUFFER, mFboIdSrc); + } + + void GRenderContext::setType(std::string type) + { + if (type == "2d") + { + initCanvas2d(); + } + else if (type == "webgl") + { + initCanvasWebGL(); + } g_RenderContextVC.push_back(this); } + void GRenderContext::initCanvasWebGL() + { + // mCanvasWebGL = std::make_shared("node-gcanvas"); + } GLuint GRenderContext::createFBO(int fboWidth, int fboHeight, GLuint *renderBufferId, GLuint *depthBufferId) { GLuint fboId2Ret = 0; @@ -155,7 +162,6 @@ namespace NodeBinding return fboId2Ret; } - void GRenderContext::makeCurrent() { if (mEglContext != EGL_NO_CONTEXT && mEglDisplay != EGL_NO_DISPLAY) @@ -165,7 +171,7 @@ namespace NodeBinding EGLSurface currentSurface = eglGetCurrentSurface(EGL_DRAW); if (mEglContext == currentContext && mEglSurface == currentSurface) { - this->BindFBO(); + BindFBO(); return; } else @@ -175,30 +181,35 @@ namespace NodeBinding printf("eglMakeCurrent fail \n"); exit(-1); } - this->BindFBO(); + BindFBO(); return; } } } - void GRenderContext::initCanvas() + void GRenderContext::initCanvas2d() { - mCanvas->CreateContext(); - mCanvas->GetGCanvasContext()->SetClearColor(gcanvas::StrValueToColorRGBA("transparent")); - mCanvas->GetGCanvasContext()->ClearScreen(); - mCanvas->GetGCanvasContext()->SetDevicePixelRatio(mRatio); - mCanvas->OnSurfaceChanged(0, 0, mCanvasWidth, mCanvasHeight); + GCanvasConfig config = {true, false}; + mCanvas2d = std::make_shared("node-gcanvas", config, nullptr); + mCanvas2d->CreateContext(); + mCanvas2d->GetGCanvasContext()->SetClearColor(gcanvas::StrValueToColorRGBA("transparent")); + mCanvas2d->GetGCanvasContext()->ClearScreen(); + mCanvas2d->GetGCanvasContext()->SetDevicePixelRatio(mDpi); + mCanvas2d->OnSurfaceChanged(0, 0, mCanvasWidth, mCanvasHeight); } void GRenderContext::drawFrame() { - mCanvas->drawFrame(); - this->drawCount++; + if (mCanvas2d) + { + mCanvas2d->drawFrame(); + } + drawCount++; } int GRenderContext::getImagePixelPNG(std::vector &in) { unsigned char *data = new unsigned char[4 * mWidth * mHeight]; - int ret = this->readPixelAndSampleFromCurrentCtx(data); + int ret = readPixelAndSampleFromCurrentCtx(data); if (ret == 0) { encodePNGInBuffer(in, data, mWidth, mHeight); @@ -217,7 +228,7 @@ namespace NodeBinding int GRenderContext::getImagePixelJPG(unsigned char **in, unsigned long &size) { unsigned char *data = new unsigned char[4 * mWidth * mHeight]; - int ret = this->readPixelAndSampleFromCurrentCtx(data); + int ret = readPixelAndSampleFromCurrentCtx(data); if (ret == 0) { encodeJPEGInBuffer(in, size, data, mWidth, mHeight); @@ -235,8 +246,8 @@ namespace NodeBinding int GRenderContext::readPixelAndSampleFromCurrentCtx(unsigned char *data) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, this->mFboIdSrc); // src FBO (multi-sample) - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, this->mFboIdDes); + glBindFramebuffer(GL_READ_FRAMEBUFFER, mFboIdSrc); // src FBO (multi-sample) + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFboIdDes); glBlitFramebuffer(0, 0, mCanvasWidth, mCanvasHeight, // src rect 0, 0, mWidth, mHeight, // dst rect GL_COLOR_BUFFER_BIT, // buffer mask @@ -249,14 +260,19 @@ namespace NodeBinding 0, 0, mWidth, mHeight, // dst rect GL_STENCIL_BUFFER_BIT, // buffer mask GL_LINEAR); - glBindFramebuffer(GL_FRAMEBUFFER, this->mFboIdDes); + glBindFramebuffer(GL_FRAMEBUFFER, mFboIdDes); glReadPixels(0, 0, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, data); return 0; } + + int GRenderContext::getDpi() + { + return mDpi; + } void GRenderContext::render2file(std::string fileName, PIC_FORMAT format) { unsigned char *data = new unsigned char[4 * mWidth * mHeight]; - int ret = this->readPixelAndSampleFromCurrentCtx(data); + int ret = readPixelAndSampleFromCurrentCtx(data); if (ret == 0) { if (format == PNG_FORAMT) @@ -280,33 +296,33 @@ namespace NodeBinding void GRenderContext::destoryRenderEnviroment() { - if (this->mFboIdSrc != 0) + if (mFboIdSrc != 0) { - glDeleteFramebuffers(1, &this->mFboIdSrc); + glDeleteFramebuffers(1, &mFboIdSrc); } - if (this->mFboIdDes != 0) + if (mFboIdDes != 0) { - glDeleteFramebuffers(1, &this->mFboIdDes); + glDeleteFramebuffers(1, &mFboIdDes); } - if (this->mRenderBufferIdSrc != 0) + if (mRenderBufferIdSrc != 0) { - glDeleteRenderbuffers(1, &this->mRenderBufferIdSrc); + glDeleteRenderbuffers(1, &mRenderBufferIdSrc); } - if (this->mRenderBufferIdDes != 0) + if (mRenderBufferIdDes != 0) { - glDeleteRenderbuffers(1, &this->mRenderBufferIdDes); + glDeleteRenderbuffers(1, &mRenderBufferIdDes); } - if (this->mDepthRenderbufferIdSrc != 0) + if (mDepthRenderbufferIdSrc != 0) { - glDeleteRenderbuffers(1, &this->mDepthRenderbufferIdSrc); + glDeleteRenderbuffers(1, &mDepthRenderbufferIdSrc); } - if (this->mDepthRenderbufferIdDes != 0) + if (mDepthRenderbufferIdDes != 0) { - glDeleteRenderbuffers(1, &this->mDepthRenderbufferIdDes); + glDeleteRenderbuffers(1, &mDepthRenderbufferIdDes); } - if (this->textures.size() > 0) + if (textures.size() > 0) { - glDeleteTextures(this->textures.size(), (GLuint *)&textures[0]); + glDeleteTextures(textures.size(), (GLuint *)&textures[0]); } if (mEglSurface != EGL_NO_SURFACE) @@ -338,7 +354,7 @@ namespace NodeBinding void GRenderContext::recordTextures(int textureId) { - this->textures.push_back(textureId); + textures.push_back(textureId); } void GRenderContext::BindFBO() @@ -357,7 +373,7 @@ namespace NodeBinding void GRenderContext::recordImageTexture(std::string url, int textureId) { - this->imageTextureMap[url] = textureId; + imageTextureMap[url] = textureId; } void GRenderContext::InitSharedContextIfNot() @@ -405,20 +421,9 @@ namespace NodeBinding } } } - int GRenderContext::getTextureIdByUrl(std::string url) - { - if (this->imageTextureMap.find(url) == imageTextureMap.end()) - { - return -1; - } - else - { - return this->imageTextureMap[url]; - } - } GRenderContext::~GRenderContext() { - this->destoryRenderEnviroment(); + destoryRenderEnviroment(); } } // namespace NodeBinding diff --git a/node/binding/renderContext/GRenderContext.h b/node/binding/renderContext/GRenderContext.h new file mode 100644 index 00000000..a7790d0b --- /dev/null +++ b/node/binding/renderContext/GRenderContext.h @@ -0,0 +1,88 @@ +/** + * Created by G-Canvas Open Source Team. + * Copyright (c) 2017, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information, please view + * the LICENSE file in the root directory of this source tree. + */ +#define CONTEXT_ES20 +#ifndef GBACKEND_H +#define GBACKEND_H +#include +#include +#include "lodepng.h" +#include +#include +#include +#include "GConvert.h" +#include "GWebGLRenderContext.hpp" +#include "NodeBindingUtil.h" +#include "Util.h" +#include "GFrameBufferObject.h" + +namespace NodeBinding +{ + extern void encodePixelsToPNGFile(std::string filename, uint8_t *buffer, int width, int height); + extern void decodeFile2Pixels(std::string filename, std::vector &image); + extern void encodePixelsToJPEGFile(std::string filename, uint8_t *buffer, int width, int height); + extern void encodePNGInBuffer(std::vector &in, unsigned char *data, int width, int height); + extern void encodeJPEGInBuffer(unsigned char **in, unsigned long &size, unsigned char *data, int width, int height); + class GRenderContext + { + public: + GRenderContext() : mWidth(0), mHeight(0), mCanvas2d(nullptr) + { + } + GRenderContext(int width, int height); + GRenderContext(int width, int height, int ratio); + virtual ~GRenderContext(); + void initRenderEnviroment(); + void render2file(std::string caseName, PIC_FORMAT format); + void drawFrame(); + void setType(std::string type); + GCanvasContext *getCtx2d() { return mCanvas2d->GetGCanvasContext(); } + std::shared_ptr getCtxWebGL() + { + return mCanvasWebGL; + } + int inline getWdith() { return mWidth; } + int inline getHeight() { return mHeight; } + void destoryRenderEnviroment(); + void recordTextures(int textureId); + void recordImageTexture(std::string url, int textureId); + int getTextureIdByUrl(std::string url); + void BindFBO(); + void makeCurrent(); + int getImagePixelPNG(std::vector &in); + int getImagePixelJPG(unsigned char **data, unsigned long &size); + int readPixelAndSampleFromCurrentCtx(unsigned char *data); + int getDpi(); + private: + std::shared_ptr mCanvas2d; + std::shared_ptr mCanvasWebGL; + void initCanvas2d(); + int mHeight; + int mWidth; + int mCanvasHeight; + int mCanvasWidth; + int mDpi; + int drawCount = 0; + EGLDisplay mEglDisplay; + EGLSurface mEglSurface; + EGLContext mEglContext; + GLuint mFboIdSrc = 0; + GLuint mRenderBufferIdSrc = 0; + GLuint mDepthRenderbufferIdSrc = 0; + std::vector textures; + std::unordered_map imageTextureMap; + static void InitSharedContextIfNot(); + GLuint createFBO(int fboWidth, int fboHeigh, GLuint *renderBufferId, GLuint *depthBufferId); + GLuint mFboIdDes = 0; + GLuint mRenderBufferIdDes = 0; + GLuint mDepthRenderbufferIdDes = 0; + void initCanvasWebGL(); + }; +} // namespace NodeBinding + +#endif \ No newline at end of file diff --git a/node/util/NodeBindingUtil.cc b/node/binding/util/NodeBindingUtil.cc similarity index 96% rename from node/util/NodeBindingUtil.cc rename to node/binding/util/NodeBindingUtil.cc index e3e59a19..f004516e 100644 --- a/node/util/NodeBindingUtil.cc +++ b/node/binding/util/NodeBindingUtil.cc @@ -38,7 +38,7 @@ writeMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) } bool checkArgs(const Napi::CallbackInfo &info, int exectedNumber) { - if (info.Length() != exectedNumber) + if (info.Length() < exectedNumber) { throwError(info, "wrong argument number"); return false; @@ -290,4 +290,18 @@ void encodePNGInBuffer(std::vector &in,unsigned char *data,int wi lodepng::encode(in, data, width, height); } +#ifdef ENABLE_CHECK_GL_ERROR +void CheckGLError(const char* stmt, const char* fname, int line) +{ + GLenum err = glGetError(); + if (err != GL_NO_ERROR){ + printf("GL error 0x%08x, at %s:%i - for `%s`\n", err, fname, line, stmt); + } + else + { + printf("GL call `%s` -> success\n", stmt); + } +} +#endif + } // namespace NodeBinding \ No newline at end of file diff --git a/node/util/NodeBindingUtil.h b/node/binding/util/NodeBindingUtil.h similarity index 81% rename from node/util/NodeBindingUtil.h rename to node/binding/util/NodeBindingUtil.h index a6215b59..53459b89 100644 --- a/node/util/NodeBindingUtil.h +++ b/node/binding/util/NodeBindingUtil.h @@ -11,6 +11,8 @@ #include #include #include "ImageCahced.h" +#include "GGL.h" + #define TIMEOUT_VALUE 5L namespace NodeBinding { @@ -35,5 +37,21 @@ bool checkArgs(const Napi::CallbackInfo &info, int exectedN); unsigned int downloadImage(const std::string &src, ImageContent *content); void throwError(const Napi::CallbackInfo &info, const std::string &exception); void throwError(const Napi::Env &env, const std::string &exception); + + +#define ENABLE_CHECK_GL_ERROR +#ifdef ENABLE_CHECK_GL_ERROR +void CheckGLError(const char* stmt, const char* fname, int line); +#define GL_CHECK(stmt) \ + stmt; \ + CheckGLError(#stmt, __FILE__, __LINE__); + +#else +#define GL_CHECK(stmt) \ + do{ \ + stmt; \ + } while (0) +#endif + } // namespace NodeBinding #endif \ No newline at end of file diff --git a/node/binding/webgl/WebGLActiveInfo.cc b/node/binding/webgl/WebGLActiveInfo.cc new file mode 100644 index 00000000..9453c9b4 --- /dev/null +++ b/node/binding/webgl/WebGLActiveInfo.cc @@ -0,0 +1,45 @@ +/** + * Created by G-Canvas Open Source Team. + * Copyright (c) 2017, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information, please view + * the LICENSE file in the root directory of this source tree. + */ +#include "WebGLActiveInfo.h" + +namespace NodeBinding +{ + Napi::FunctionReference WebGLActiveInfo::constructor; + WebGLActiveInfo::WebGLActiveInfo(const Napi::CallbackInfo &info) : Napi::ObjectWrap(info) + { + this->mSize = info[0].As().Int32Value(); + this->mType = info[1].As().Int32Value(); + this->mName = info[2].As().Utf8Value(); + } + + void WebGLActiveInfo::Init(Napi::Env env) + { + Napi::HandleScope scope(env); + + Napi::Function func = + DefineClass(env, + "WebGLActiveInfo", + + {InstanceAccessor("name", &WebGLActiveInfo::getName, nullptr), + InstanceAccessor("size", &WebGLActiveInfo::getSize, nullptr), + InstanceAccessor("type", &WebGLActiveInfo::getType, nullptr)}); + constructor = Napi::Persistent(func); + constructor.SuppressDestruct(); + } + + Napi::Object WebGLActiveInfo::NewInstance(Napi::Env env, GLuint size, GLuint type, GLchar *buffer) + { + + Napi::Object obj = constructor.New({Napi::Number::New(env, size), + Napi::Number::New(env, type), + Napi::String::New(env, buffer)}); + return obj; + // return obj; + } +} // namespace NodeBinding \ No newline at end of file diff --git a/node/binding/webgl/WebGLActiveInfo.h b/node/binding/webgl/WebGLActiveInfo.h new file mode 100644 index 00000000..a9dc4651 --- /dev/null +++ b/node/binding/webgl/WebGLActiveInfo.h @@ -0,0 +1,34 @@ +#ifndef WebGLACTIVERINFO_H +#define WebGLACTIVERINFO_H +#include +#include +#include +namespace NodeBinding +{ + class WebGLActiveInfo : public Napi::ObjectWrap + { + public: + WebGLActiveInfo(const Napi::CallbackInfo &info); + static void Init(Napi::Env env); + static Napi::Object NewInstance(Napi::Env env, GLuint size, GLuint type, GLchar *buffer); + + private: + Napi::Value getName(const Napi::CallbackInfo &info) + { + return Napi::String::New(info.Env(), this->mName); + } + Napi::Value getSize(const Napi::CallbackInfo &info) + { + return Napi::Number::New(info.Env(), this->mSize); + } + Napi::Value getType(const Napi::CallbackInfo &info) + { + return Napi::Number::New(info.Env(), this->mType); + } + static Napi::FunctionReference constructor; + GLint mType; + GLint mSize; + std::string mName; + }; +} // namespace NodeBinding +#endif \ No newline at end of file diff --git a/node/binding/webgl/WebGLBuffer.cc b/node/binding/webgl/WebGLBuffer.cc new file mode 100644 index 00000000..831525b7 --- /dev/null +++ b/node/binding/webgl/WebGLBuffer.cc @@ -0,0 +1,38 @@ +/** + * Created by G-Canvas Open Source Team. + * Copyright (c) 2017, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information, please view + * the LICENSE file in the root directory of this source tree. + */ +#include "WebGLBuffer.h" + +namespace NodeBinding +{ +Napi::FunctionReference WebGLBuffer::constructor; +WebGLBuffer::WebGLBuffer(const Napi::CallbackInfo &info) : Napi::ObjectWrap(info) +{ + this->mId = info[0].As().Uint32Value(); +} + +void WebGLBuffer::Init(Napi::Env env) +{ + Napi::HandleScope scope(env); + + Napi::Function func = + DefineClass(env, + "WebGLBuffer", + { + + }); + constructor = Napi::Persistent(func); + constructor.SuppressDestruct(); +} + +Napi::Object WebGLBuffer::NewInstance(Napi::Env env, const Napi::Value arg) +{ + Napi::Object obj = constructor.New({arg}); + return obj; +} +} // namespace NodeBinding \ No newline at end of file diff --git a/node/binding/webgl/WebGLBuffer.h b/node/binding/webgl/WebGLBuffer.h new file mode 100644 index 00000000..f61aca9f --- /dev/null +++ b/node/binding/webgl/WebGLBuffer.h @@ -0,0 +1,23 @@ +#ifndef WEBGLBUFFER_H +#define WEBGLBUFFER_H +#include +#include +namespace NodeBinding +{ + class WebGLBuffer : public Napi::ObjectWrap + { + public: + WebGLBuffer(const Napi::CallbackInfo &info); + static void Init(Napi::Env env); + static Napi::Object NewInstance(Napi::Env env, const Napi::Value arg); + inline GLuint getId() const + { + return this->mId; + } + + private: + GLuint mId = 0; + static Napi::FunctionReference constructor; + }; +} // namespace NodeBinding +#endif \ No newline at end of file diff --git a/node/binding/webgl/WebGLFrameBuffer.cc b/node/binding/webgl/WebGLFrameBuffer.cc new file mode 100644 index 00000000..e5c52585 --- /dev/null +++ b/node/binding/webgl/WebGLFrameBuffer.cc @@ -0,0 +1,38 @@ +/** + * Created by G-Canvas Open Source Team. + * Copyright (c) 2017, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information, please view + * the LICENSE file in the root directory of this source tree. + */ +#include "WebGLFrameBuffer.h" + +namespace NodeBinding +{ +Napi::FunctionReference WebGLFrameBuffer::constructor; +WebGLFrameBuffer::WebGLFrameBuffer(const Napi::CallbackInfo &info) : Napi::ObjectWrap(info) +{ + this->mId = info[0].As().Uint32Value(); +} + +void WebGLFrameBuffer::Init(Napi::Env env) +{ + Napi::HandleScope scope(env); + + Napi::Function func = + DefineClass(env, + "WebGLFrameBuffer", + { + + }); + constructor = Napi::Persistent(func); + constructor.SuppressDestruct(); +} + +Napi::Object WebGLFrameBuffer::NewInstance(Napi::Env env, const Napi::Value arg) +{ + Napi::Object obj = constructor.New({arg}); + return obj; +} +} // namespace NodeBinding \ No newline at end of file diff --git a/node/binding/webgl/WebGLFrameBuffer.h b/node/binding/webgl/WebGLFrameBuffer.h new file mode 100644 index 00000000..9841e3b4 --- /dev/null +++ b/node/binding/webgl/WebGLFrameBuffer.h @@ -0,0 +1,23 @@ +#ifndef WEBGLFRAMEBUFFER_H +#define WEBGLFRAMEBUFFER_H +#include +#include +namespace NodeBinding +{ + class WebGLFrameBuffer : public Napi::ObjectWrap + { + public: + WebGLFrameBuffer(const Napi::CallbackInfo &info); + static void Init(Napi::Env env); + static Napi::Object NewInstance(Napi::Env env, const Napi::Value arg); + inline GLuint getId() const + { + return this->mId; + } + + private: + GLuint mId = 0; + static Napi::FunctionReference constructor; + }; +} // namespace NodeBinding +#endif \ No newline at end of file diff --git a/node/binding/webgl/WebGLProgram.cc b/node/binding/webgl/WebGLProgram.cc new file mode 100644 index 00000000..e8993394 --- /dev/null +++ b/node/binding/webgl/WebGLProgram.cc @@ -0,0 +1,38 @@ +/** + * Created by G-Canvas Open Source Team. + * Copyright (c) 2017, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information, please view + * the LICENSE file in the root directory of this source tree. + */ +#include "WebGLProgram.h" + +namespace NodeBinding +{ +Napi::FunctionReference WebGLProgram::constructor; +WebGLProgram::WebGLProgram(const Napi::CallbackInfo &info) : Napi::ObjectWrap(info) +{ + this->mId = info[0].As().Uint32Value(); +} + +void WebGLProgram::Init(Napi::Env env) +{ + Napi::HandleScope scope(env); + + Napi::Function func = + DefineClass(env, + "WebGLShader", + { + + }); + constructor = Napi::Persistent(func); + constructor.SuppressDestruct(); +} + +Napi::Object WebGLProgram::NewInstance(Napi::Env env, const Napi::Value arg) +{ + Napi::Object obj = constructor.New({arg}); + return obj; +} +} // namespace NodeBinding \ No newline at end of file diff --git a/node/binding/webgl/WebGLProgram.h b/node/binding/webgl/WebGLProgram.h new file mode 100644 index 00000000..36a6c5b2 --- /dev/null +++ b/node/binding/webgl/WebGLProgram.h @@ -0,0 +1,23 @@ +#ifndef WEBGLPROGRAM_H +#define WEBGLPROGRAM_H +#include +#include +namespace NodeBinding +{ + class WebGLProgram : public Napi::ObjectWrap + { + public: + WebGLProgram(const Napi::CallbackInfo &info); + static void Init(Napi::Env env); + static Napi::Object NewInstance(Napi::Env env, const Napi::Value arg); + inline GLuint getId() const + { + return this->mId; + } + + private: + GLuint mId = 0; + static Napi::FunctionReference constructor; + }; +} // namespace NodeBinding +#endif \ No newline at end of file diff --git a/node/binding/webgl/WebGLRenderBuffer.cc b/node/binding/webgl/WebGLRenderBuffer.cc new file mode 100644 index 00000000..ddb24268 --- /dev/null +++ b/node/binding/webgl/WebGLRenderBuffer.cc @@ -0,0 +1,38 @@ +/** + * Created by G-Canvas Open Source Team. + * Copyright (c) 2017, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information, please view + * the LICENSE file in the root directory of this source tree. + */ +#include "WebGLRenderBuffer.h" + +namespace NodeBinding +{ +Napi::FunctionReference WebGLRenderBuffer::constructor; +WebGLRenderBuffer::WebGLRenderBuffer(const Napi::CallbackInfo &info) : Napi::ObjectWrap(info) +{ + this->mId = info[0].As().Uint32Value(); +} + +void WebGLRenderBuffer::Init(Napi::Env env) +{ + Napi::HandleScope scope(env); + + Napi::Function func = + DefineClass(env, + "WebGLRenderBuffer", + { + + }); + constructor = Napi::Persistent(func); + constructor.SuppressDestruct(); +} + +Napi::Object WebGLRenderBuffer::NewInstance(Napi::Env env, const Napi::Value arg) +{ + Napi::Object obj = constructor.New({arg}); + return obj; +} +} // namespace NodeBinding \ No newline at end of file diff --git a/node/binding/webgl/WebGLRenderBuffer.h b/node/binding/webgl/WebGLRenderBuffer.h new file mode 100644 index 00000000..7266e5f6 --- /dev/null +++ b/node/binding/webgl/WebGLRenderBuffer.h @@ -0,0 +1,23 @@ +#ifndef WEBGLRENDERBUFFER_H +#define WEBGLRENDERBUFFER_H +#include +#include +namespace NodeBinding +{ + class WebGLRenderBuffer : public Napi::ObjectWrap + { + public: + WebGLRenderBuffer(const Napi::CallbackInfo &info); + static void Init(Napi::Env env); + static Napi::Object NewInstance(Napi::Env env, const Napi::Value arg); + inline GLuint getId() const + { + return this->mId; + } + + private: + GLuint mId = 0; + static Napi::FunctionReference constructor; + }; +} // namespace NodeBinding +#endif \ No newline at end of file diff --git a/node/binding/webgl/WebGLShader.cc b/node/binding/webgl/WebGLShader.cc new file mode 100644 index 00000000..e673eef7 --- /dev/null +++ b/node/binding/webgl/WebGLShader.cc @@ -0,0 +1,38 @@ +/** + * Created by G-Canvas Open Source Team. + * Copyright (c) 2017, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information, please view + * the LICENSE file in the root directory of this source tree. + */ +#include "WebGLShader.h" + +namespace NodeBinding +{ +Napi::FunctionReference WebGLShader::constructor; +WebGLShader::WebGLShader(const Napi::CallbackInfo &info) : Napi::ObjectWrap(info) +{ + this->mId = info[0].As().Uint32Value(); +} + +void WebGLShader::Init(Napi::Env env) +{ + Napi::HandleScope scope(env); + + Napi::Function func = + DefineClass(env, + "WebGLShader", + { + + }); + constructor = Napi::Persistent(func); + constructor.SuppressDestruct(); +} + +Napi::Object WebGLShader::NewInstance(Napi::Env env, const Napi::Value arg) +{ + Napi::Object obj = constructor.New({arg}); + return obj; +} +} // namespace NodeBinding \ No newline at end of file diff --git a/node/binding/webgl/WebGLShader.h b/node/binding/webgl/WebGLShader.h new file mode 100644 index 00000000..03cfbead --- /dev/null +++ b/node/binding/webgl/WebGLShader.h @@ -0,0 +1,23 @@ +#ifndef WEBGLSHADER_H +#define WEBGLSHADER_H +#include +#include +namespace NodeBinding +{ + class WebGLShader : public Napi::ObjectWrap + { + public: + WebGLShader(const Napi::CallbackInfo &info); + static void Init(Napi::Env env); + static Napi::Object NewInstance(Napi::Env env, const Napi::Value arg); + inline GLuint getId() const + { + return this->mId; + } + + private: + GLuint mId = 0; + static Napi::FunctionReference constructor; + }; +} // namespace NodeBinding +#endif \ No newline at end of file diff --git a/node/binding/webgl/WebGLTexture.cc b/node/binding/webgl/WebGLTexture.cc new file mode 100644 index 00000000..7a10660d --- /dev/null +++ b/node/binding/webgl/WebGLTexture.cc @@ -0,0 +1,38 @@ +/** + * Created by G-Canvas Open Source Team. + * Copyright (c) 2017, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information, please view + * the LICENSE file in the root directory of this source tree. + */ +#include "WebGLTexture.h" + +namespace NodeBinding +{ +Napi::FunctionReference WebGLTexture::constructor; +WebGLTexture::WebGLTexture(const Napi::CallbackInfo &info) : Napi::ObjectWrap(info) +{ + this->mId = info[0].As().Uint32Value(); +} + +void WebGLTexture::Init(Napi::Env env) +{ + Napi::HandleScope scope(env); + + Napi::Function func = + DefineClass(env, + "WebGLTexture", + { + + }); + constructor = Napi::Persistent(func); + constructor.SuppressDestruct(); +} + +Napi::Object WebGLTexture::NewInstance(Napi::Env env, const Napi::Value arg) +{ + Napi::Object obj = constructor.New({arg}); + return obj; +} +} // namespace NodeBinding \ No newline at end of file diff --git a/node/binding/webgl/WebGLTexture.h b/node/binding/webgl/WebGLTexture.h new file mode 100644 index 00000000..8960b352 --- /dev/null +++ b/node/binding/webgl/WebGLTexture.h @@ -0,0 +1,23 @@ +#ifndef WEBGLTEXTURE_H +#define WEBGLTEXTURE_H +#include +#include +namespace NodeBinding +{ + class WebGLTexture : public Napi::ObjectWrap + { + public: + WebGLTexture(const Napi::CallbackInfo &info); + static void Init(Napi::Env env); + static Napi::Object NewInstance(Napi::Env env, const Napi::Value arg); + inline GLuint getId() const + { + return this->mId; + } + + private: + GLuint mId = 0; + static Napi::FunctionReference constructor; + }; +} // namespace NodeBinding +#endif \ No newline at end of file diff --git a/node/binding/webgl/WebGLUniformLocation.cc b/node/binding/webgl/WebGLUniformLocation.cc new file mode 100644 index 00000000..766cece6 --- /dev/null +++ b/node/binding/webgl/WebGLUniformLocation.cc @@ -0,0 +1,37 @@ +/** + * Created by G-Canvas Open Source Team. + * Copyright (c) 2017, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information, please view + * the LICENSE file in the root directory of this source tree. + */ +#include "WebGLUniformLocation.h" + +namespace NodeBinding +{ + Napi::FunctionReference WebGLUniformLocation::constructor; + WebGLUniformLocation::WebGLUniformLocation(const Napi::CallbackInfo &info) : Napi::ObjectWrap(info) + { + this->mIndex = info[0].As().Uint32Value(); + } + + void WebGLUniformLocation::Init(Napi::Env env) + { + Napi::HandleScope scope(env); + + Napi::Function func = + DefineClass(env, + "WebGLUniformLocation", + {}); + constructor = Napi::Persistent(func); + constructor.SuppressDestruct(); + } + + Napi::Object WebGLUniformLocation::NewInstance(Napi::Env env, GLuint index) + { + + Napi::Object obj = constructor.New({Napi::Number::New(env, index)}); + return obj; + } +} // namespace NodeBinding \ No newline at end of file diff --git a/node/binding/webgl/WebGLUniformLocation.h b/node/binding/webgl/WebGLUniformLocation.h new file mode 100644 index 00000000..19161007 --- /dev/null +++ b/node/binding/webgl/WebGLUniformLocation.h @@ -0,0 +1,23 @@ +#ifndef WebGLUniformLocation_H +#define WebGLUniformLocation_H +#include +#include +#include +namespace NodeBinding +{ + class WebGLUniformLocation : public Napi::ObjectWrap + { + public: + WebGLUniformLocation(const Napi::CallbackInfo &info); + static void Init(Napi::Env env); + static Napi::Object NewInstance(Napi::Env env, GLuint index); + inline GLuint getIndex(){ + return this->mIndex; + } + private: + + static Napi::FunctionReference constructor; + GLuint mIndex; + }; +} // namespace NodeBinding +#endif \ No newline at end of file diff --git a/node/examples/webgl/glclearColor.js b/node/examples/webgl/glclearColor.js new file mode 100644 index 00000000..efbe8b40 --- /dev/null +++ b/node/examples/webgl/glclearColor.js @@ -0,0 +1,16 @@ +const { createCanvas, Image } = require('../../export') +const fs = require('fs') +const path = require('path'); +const out = fs.createWriteStream(path.join(__dirname, "..","..")+ '/clearcolor.png'); + +const canvas = createCanvas(400, 400); +var gl = canvas.getContext("webgl"); + +gl.viewport(0,0,canvas.width,canvas.height); +gl.clearColor(1.0, 0.5, 0.5, 1.0); +gl.clear(gl.COLOR_BUFFER_BIT); + +var stream = canvas.createPNGStream(); +stream.on('data', function (chunk) { + out.write(chunk); +}); \ No newline at end of file diff --git a/node/examples/webgl/glcube.js b/node/examples/webgl/glcube.js new file mode 100644 index 00000000..c621eb03 --- /dev/null +++ b/node/examples/webgl/glcube.js @@ -0,0 +1,206 @@ +const { createCanvas, Image } = require('../../export') +const fs = require('fs') +const path = require('path'); +const out = fs.createWriteStream(path.join(__dirname, "..","..")+ '/cube.png'); + +const canvas = createCanvas(400, 400); +var gl = canvas.getContext("webgl"); + +var width = canvas.width; +var height = canvas.height; + +/*========== Defining and storing the geometry ==========*/ +var vertices = [ + -1,-1,-1, 1,-1,-1, 1, 1,-1, -1, 1,-1, + -1,-1, 1, 1,-1, 1, 1, 1, 1, -1, 1, 1, + -1,-1,-1, -1, 1,-1, -1, 1, 1, -1,-1, 1, + 1,-1,-1, 1, 1,-1, 1, 1, 1, 1,-1, 1, + -1,-1,-1, -1,-1, 1, 1,-1, 1, 1,-1,-1, + -1, 1,-1, -1, 1, 1, 1, 1, 1, 1, 1,-1, + ]; + +var colors = [ + 5,3,7, 5,3,7, 5,3,7, 5,3,7, + 1,1,3, 1,1,3, 1,1,3, 1,1,3, + 0,0,1, 0,0,1, 0,0,1, 0,0,1, + 1,0,0, 1,0,0, 1,0,0, 1,0,0, + 1,1,0, 1,1,0, 1,1,0, 1,1,0, + 0,1,0, 0,1,0, 0,1,0, 0,1,0 + ]; + +var indices = [ + 0,1,2, 0,2,3, 4,5,6, 4,6,7, + 8,9,10, 8,10,11, 12,13,14, 12,14,15, + 16,17,18, 16,18,19, 20,21,22, 20,22,23 + ]; + +// Create and store data into vertex buffer +var vertex_buffer = gl.createBuffer (); +gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); +gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); + +// Create and store data into color buffer +var color_buffer = gl.createBuffer (); +gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer); +gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW); + +// Create and store data into index buffer +var index_buffer = gl.createBuffer (); +gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer); +gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); + +/*=================== Shaders =========================*/ + +var vertCode = 'attribute vec3 position;'+ +'uniform mat4 Pmatrix;'+ +'uniform mat4 Vmatrix;'+ +'uniform mat4 Mmatrix;'+ +'attribute vec3 color;'+//the color of the point +'varying vec3 vColor;'+ + +'void main(void) { '+//pre-built function +'gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(position, 1.);'+ +'vColor = color;'+ +'}'; + +var fragCode = 'precision mediump float;'+ +'varying vec3 vColor;'+ +'void main(void) {'+ +'gl_FragColor = vec4(vColor, 1.);'+ +'}'; + +var vertShader = gl.createShader(gl.VERTEX_SHADER); +gl.shaderSource(vertShader, vertCode); +gl.compileShader(vertShader); + +var fragShader = gl.createShader(gl.FRAGMENT_SHADER); +gl.shaderSource(fragShader, fragCode); +gl.compileShader(fragShader); + +var shaderProgram = gl.createProgram(); +gl.attachShader(shaderProgram, vertShader); +gl.attachShader(shaderProgram, fragShader); +gl.linkProgram(shaderProgram); + +/* ====== Associating attributes to vertex shader =====*/ +var Pmatrix = gl.getUniformLocation(shaderProgram, "Pmatrix"); +var Vmatrix = gl.getUniformLocation(shaderProgram, "Vmatrix"); +var Mmatrix = gl.getUniformLocation(shaderProgram, "Mmatrix"); + +gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); +var position = gl.getAttribLocation(shaderProgram, "position"); +gl.vertexAttribPointer(position, 3, gl.FLOAT, false,0,0) ; + +// Position +gl.enableVertexAttribArray(position); +gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer); +var color = gl.getAttribLocation(shaderProgram, "color"); +gl.vertexAttribPointer(color, 3, gl.FLOAT, false,0,0) ; + +// Color +gl.enableVertexAttribArray(color); +gl.useProgram(shaderProgram); + +/*==================== MATRIX =====================*/ + +function get_projection(angle, a, zMin, zMax) { + var ang = Math.tan((angle*.5)*Math.PI/180);//angle*.5 + return [ + 0.5/ang, 0 , 0, 0, + 0, 0.5*a/ang, 0, 0, + 0, 0, -(zMax+zMin)/(zMax-zMin), -1, + 0, 0, (-2*zMax*zMin)/(zMax-zMin), 0 + ]; +} + + +var proj_matrix = get_projection(40, width/height, 1, 100); + +var mov_matrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]; +var view_matrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]; + +// translating z +view_matrix[14] = view_matrix[14]-6;//zoom + +/*==================== Rotation ====================*/ + +function rotateZ(m, angle) { + var c = Math.cos(angle); + var s = Math.sin(angle); + var mv0 = m[0], mv4 = m[4], mv8 = m[8]; + + m[0] = c*m[0]-s*m[1]; + m[4] = c*m[4]-s*m[5]; + m[8] = c*m[8]-s*m[9]; + + m[1]=c*m[1]+s*mv0; + m[5]=c*m[5]+s*mv4; + m[9]=c*m[9]+s*mv8; +} + +function rotateX(m, angle) { + var c = Math.cos(angle); + var s = Math.sin(angle); + var mv1 = m[1], mv5 = m[5], mv9 = m[9]; + + m[1] = m[1]*c-m[2]*s; + m[5] = m[5]*c-m[6]*s; + m[9] = m[9]*c-m[10]*s; + + m[2] = m[2]*c+mv1*s; + m[6] = m[6]*c+mv5*s; + m[10] = m[10]*c+mv9*s; +} + +function rotateY(m, angle) { + var c = Math.cos(angle); + var s = Math.sin(angle); + var mv0 = m[0], mv4 = m[4], mv8 = m[8]; + + m[0] = c*m[0]+s*m[2]; + m[4] = c*m[4]+s*m[6]; + m[8] = c*m[8]+s*m[10]; + + m[2] = c*m[2]-s*mv0; + m[6] = c*m[6]-s*mv4; + m[10] = c*m[10]-s*mv8; +} + +/*=================Drawing===========================*/ + +var time_old = 0; +//var time = 0; +var time = 250; + +var draw = function() { + var dt = time-time_old; + rotateZ(mov_matrix, dt*0.005);//time + rotateY(mov_matrix, dt*0.002); + rotateX(mov_matrix, dt*0.003); + time_old = time; + time += 16; + + gl.enable(gl.DEPTH_TEST); + gl.depthFunc(gl.LEQUAL); + gl.clearColor(0.5, 0.5, 0.5, 0.9); + gl.clearDepth(1.0); + + gl.viewport(0.0, 0.0, width, height); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + gl.uniformMatrix4fv(Pmatrix, false, proj_matrix); + gl.uniformMatrix4fv(Vmatrix, false, view_matrix); + gl.uniformMatrix4fv(Mmatrix, false, mov_matrix); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer); + gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0); + + //requestAnimationFrame(draw); + +} + +draw(); + + +var stream = canvas.createPNGStream(); +stream.on('data', function (chunk) { + out.write(chunk); +}); \ No newline at end of file diff --git a/node/examples/webgl/gldistanceField.js b/node/examples/webgl/gldistanceField.js new file mode 100644 index 00000000..87cfa736 --- /dev/null +++ b/node/examples/webgl/gldistanceField.js @@ -0,0 +1,446 @@ +const { createCanvas, Image } = require('../../export') +const fs = require('fs') +const path = require('path'); +const out = fs.createWriteStream(path.join(__dirname, "..","..")+ '/distanceField.png'); + +const canvas = createCanvas(900, 2100); +var gl = canvas.getContext("webgl"); + +var vs_source = "attribute vec2 aVertexPosition;\ +void main()\ +{\ + gl_Position = vec4(aVertexPosition, 0.0, 1.0);\ +}"; + +var fs_source = "precision highp float;\ +\ +uniform float time;\ +uniform vec2 resolution;\ +uniform vec3 cameraPos;\ +uniform vec3 cameraLookat;\ +uniform vec3 lightDir;\ +uniform vec3 lightColour;\ +uniform float specular;\ +uniform float specularHardness;\ +uniform vec3 diffuse;\ +uniform float ambientFactor;\ +uniform bool ao;\ +uniform bool shadows;\ +uniform bool postEffects;\ +uniform bool rotateWorld;\ +uniform bool moveCamera;\ +uniform bool antialias;\ +\ +const float PI = 3.14159265;\ +const float GAMMA = 0.8;\ +const float CONTRAST = 1.1;\ +const float SATURATION = 1.3;\ +const float BRIGHTNESS = 1.3;\ +const int AO_SAMPLES = 5;\ +const int RAY_DEPTH = 256;\ +const float MAX_DEPTH = 100.0;\ +const int SHADOW_RAY_DEPTH = 32;\ +const float DISTANCE_MIN = 0.001;\ +\ +const vec2 delta = vec2(0.001, 0.);\ +\ +\ +vec3 RotateZ(vec3 p, float a)\ +{\ + float c,s;\ + vec3 q=p;\ + c = cos(a);\ + s = sin(a);\ + p.x = c * q.x - s * q.y;\ + p.y = s * q.x + c * q.y;\ + return p;\ +}\ +\ +float smax(float a, float b, float k)\ +{\ + float h = clamp(0.5+0.5*(b-a)/k, 0.0, 1.0);\ + return mix(a, b, h) - k*h*h;\ +}\ +\ +float Sphere(vec3 p, float s)\ +{\ + return length(p)-s;\ +}\ +\ +float HexPrism(vec3 p, vec2 h)\ +{\ + vec3 q = abs(p);\ + return max(q.z-h.y,max(q.x+q.y*0.57735,q.y*1.1547)-h.x);\ +}\ +\ +float Plane(vec3 p, vec3 n)\ +{\ + return dot(p, n);\ +}\ +\ +float ReplicateXZ(vec3 p, vec3 c)\ +{\ + vec3 q = vec3(mod(p.x, c.x) - 0.5 * c.x, p.y, mod(p.z, c.z) - 0.5 * c.z);\ + return\ + min(\ + Plane(q-vec3(0.,-0.85,0.), vec3(0.,1.,0.)),\ +\ + smax(\ +\ + max(\ + HexPrism(q, vec2(1.0,0.5)),\ + -HexPrism(q-vec3(0.,0.,0.25), vec2(0.8,1.0))\ + ),\ +\ + -min(\ + Sphere(q-vec3(0.,0.85,0.), 0.333),\ + min(\ + Sphere(q-vec3(0.,-0.85,0.), 0.333),\ + min(\ + Sphere(q-vec3(0.75,0.45,0.), 0.333),\ + min(\ + Sphere(q-vec3(0.75,-0.45,0.), 0.333),\ + min(\ + Sphere(q-vec3(-0.75,0.45,0.), 0.333),\ + Sphere(q-vec3(-0.75,-0.45,0.), 0.333)\ + )\ + )\ + )\ + )\ + ),0.05\ + )\ + );\ +}\ +\ +float Dist(vec3 pos)\ +{\ + if (rotateWorld) pos = RotateZ(pos, sin(time)*0.5);\ + return ReplicateXZ(pos, vec3(4.,0.,4.));\ +}\ +\ +float CalcAO(vec3 p, vec3 n)\ +{\ + float r = 0.0;\ + float w = 1.0;\ + for (int i=1; i<=AO_SAMPLES; i++)\ + {\ + float d0 = float(i) * 0.3;\ + r += w * (d0 - Dist(p + n * d0));\ + w *= 0.5;\ + }\ + return 1.0 - r;\ +}\ +\ +float SoftShadow(vec3 ro, vec3 rd, float k)\ +{\ + float res = 1.0;\ + float t = 0.05;\ + for (int i=0; i= MAX_DEPTH) break;\ + }\ + return vec4(0.0);\ +}\ +\ +void main()\ +{\ + const int ANTIALIAS_SAMPLES = 4;\ + \ + vec4 res = vec4(0.0);\ + \ + vec3 off = vec3(0.0);\ + if (moveCamera) off.z -= time*10.0;\ + \ + if (antialias)\ + {\ + vec2 p;\ + float d_ang = 2.*PI / float(ANTIALIAS_SAMPLES);\ + float ang = d_ang * 0.33333;\ + float r = 0.3;\ + for (int i = 0; i < ANTIALIAS_SAMPLES; i++)\ + {\ + p = vec2((gl_FragCoord.x + cos(ang)*r) / resolution.x, (gl_FragCoord.y + sin(ang)*r) / resolution.y);\ + vec3 ro = cameraPos + off;\ + vec3 rd = normalize(GetRay(cameraLookat-cameraPos, p));\ + vec4 _res = March(ro, rd);\ + if (_res.a == 1.0) res.rgb += Shading(_res.rgb, rd, GetNormal(_res.rgb), ro).rgb;\ + else res.rgb += Sky(rd);\ + ang += d_ang;\ + }\ + res.rgb /= float(ANTIALIAS_SAMPLES);\ + if (postEffects) res.rgb = PostEffects(res.rgb, p);\ + }\ + else\ + {\ + vec2 p = gl_FragCoord.xy / resolution.xy;\ + vec3 ro = cameraPos + off;\ + vec3 rd = normalize(GetRay((cameraLookat-off)-cameraPos+off, p));\ + \ + res = March(ro, rd);\ + if (res.a == 1.0) res.rgb = Shading(res.rgb, rd, GetNormal(res.rgb), ro).rgb;\ + else res.rgb = Sky(rd);\ + if (postEffects) res.rgb = PostEffects(res.rgb, p);\ + }\ + \ + gl_FragColor = vec4(res.rgb, 1.0);\ +}"; + + +var config = { + camera: { + x: 9.0, y: 4.5, z: 0.0 + }, + lookat: { + x: 0.0, y: -10.0, z: -100.0 + }, + lightDir: { + x: -1.4, y: 0.8, z: -1.0 + }, + lightColour: { + r: 3.0, g: 1.4, b: 0.3 + }, + surface: { + specular: 64.0, + specularHardness: 256.0, + diffuse: 0.4, + ambientFactor: 0.2 + }, + global: { + ao: true, + shadows: true, + postEffects: true, + antialias: "None",// None|Classic + rotateWorld: true, + moveCamera: true + } +}; + +var pause = false; +var aspect; +function init() { + aspect = canvas.width / canvas.height; + + console.log('canvas', canvas.width, canvas.height); + + gl.viewport(0, 0, canvas.width, canvas.height); + gl.clearColor(0, 0, 0, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + + // compile and link the shaders + var vs = gl.createShader(gl.VERTEX_SHADER); + gl.shaderSource(vs, vs_source); + gl.compileShader(vs); + + var fs = gl.createShader(gl.FRAGMENT_SHADER); + gl.shaderSource(fs, fs_source); + gl.compileShader(fs); + + var program = gl.createProgram(); + gl.attachShader(program, vs); + gl.attachShader(program, fs); + gl.linkProgram(program); + + // debug shader compile status + var error = false; + if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) { + error = true; + console.log(gl.getShaderInfoLog(vs)); + } + + if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) { + error = true; + console.log(gl.getShaderInfoLog(fs)); + } + + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + error = true; + console.log(gl.getProgramInfoLog(program)); + } + if (error) return; + + var firstTime = Date.now(); + + function render() { + if (!pause) { + //stats.begin(); + + // create vertices to fill the canvas with a single quad + var vertices = new Float32Array( + [ + -1, 1*aspect, 1, 1*aspect, 1, -1*aspect, + -1, 1*aspect, 1, -1*aspect, -1, -1*aspect + ]); + + var vbuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vbuffer); + gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); + + var triCount = 2, + numItems = vertices.length / triCount; + + gl.useProgram(program); + + var time = (Date.now() - firstTime) / 1000.0; + program.time = gl.getUniformLocation(program, "time"); + gl.uniform1f(program.time, time); + + program.resolution = gl.getUniformLocation(program, "resolution"); + gl.uniform2f(program.resolution, canvas.width, canvas.height); + + program.cameraPos = gl.getUniformLocation(program, "cameraPos"); + gl.uniform3f(program.cameraPos, config.camera.x, config.camera.y, config.camera.z); + + program.cameraLookat = gl.getUniformLocation(program, "cameraLookat"); + gl.uniform3f(program.cameraLookat, config.lookat.x, config.lookat.y, config.lookat.z); + + program.lightDir = gl.getUniformLocation(program, "lightDir"); + // pre normalise light dir + var x = config.lightDir.x, y = config.lightDir.y, z = config.lightDir.z; + var len = x*x + y*y + z*z; + len = 1.0 / Math.sqrt(len); + gl.uniform3f(program.lightDir, config.lightDir.x*len, config.lightDir.y*len, config.lightDir.z*len); + + program.lightColour = gl.getUniformLocation(program, "lightColour"); + gl.uniform3f(program.lightColour, config.lightColour.r, config.lightColour.g, config.lightColour.b); + + program.specular = gl.getUniformLocation(program, "specular"); + gl.uniform1f(program.specular, config.surface.specular); + + program.specularHardness = gl.getUniformLocation(program, "specularHardness"); + gl.uniform1f(program.specularHardness, config.surface.specularHardness); + + program.diffuse = gl.getUniformLocation(program, "diffuse"); + gl.uniform3f(program.diffuse, config.surface.diffuse,config.surface.diffuse,config.surface.diffuse); + + program.ambientFactor = gl.getUniformLocation(program, "ambientFactor"); + gl.uniform1f(program.ambientFactor, config.surface.ambientFactor); + + program.rotateWorld = gl.getUniformLocation(program, "rotateWorld"); + gl.uniform1f(program.rotateWorld, config.global.rotateWorld); + + program.moveCamera = gl.getUniformLocation(program, "moveCamera"); + gl.uniform1f(program.moveCamera, config.global.moveCamera); + + program.postEffects = gl.getUniformLocation(program, "postEffects"); + gl.uniform1f(program.postEffects, config.global.postEffects); + + program.ao = gl.getUniformLocation(program, "ao"); + gl.uniform1f(program.ao, config.global.ao); + + program.shadows = gl.getUniformLocation(program, "shadows"); + gl.uniform1f(program.shadows, config.global.shadows); + + program.antialias = gl.getUniformLocation(program, "antialias"); + gl.uniform1f(program.antialias, (config.global.antialias === "Classic")); + + program.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); + gl.enableVertexAttribArray(program.aVertexPosition); + gl.vertexAttribPointer(program.aVertexPosition, triCount, gl.FLOAT, false, 0, 0); + + gl.drawArrays(gl.TRIANGLES, 0, numItems); + + //stats.end(); + + //canvasLog("iterate frame...."); + // canvas.requestAnimationFrame(render); + } + }; + render(); +} + +console.log("init ..."); +init(); + + +var stream = canvas.createPNGStream(); +stream.on('data', function (chunk) { + out.write(chunk); +}); + +// canvas.requestAnimationFrame(render); \ No newline at end of file diff --git a/node/examples/webgl/glrectangle.js b/node/examples/webgl/glrectangle.js new file mode 100644 index 00000000..3e0f3f71 --- /dev/null +++ b/node/examples/webgl/glrectangle.js @@ -0,0 +1,124 @@ +const { createCanvas, Image } = require('../../export') +const fs = require('fs') +const path = require('path'); +const out = fs.createWriteStream(path.join(__dirname, "..","..")+ '/rectangle.png'); + +const canvas = createCanvas(1200, 700); +var gl = canvas.getContext("webgl"); + +var vertexSource = ` +attribute vec2 a_position; +uniform vec2 u_resolution; +void main() { + // convert the rectangle from pixels to 0.0 to 1.0 + vec2 zeroToOne = a_position / u_resolution; + // convert from 0->1 to 0->2 + vec2 zeroToTwo = zeroToOne * 2.0; + // convert from 0->2 to -1->+1 (clipspace) + vec2 clipSpace = zeroToTwo - 1.0; + gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); +} +`; +var fragmentSource = ` +precision mediump float; +uniform vec4 u_color; +void main() { + gl_FragColor = u_color; +} +`; + +// setup program +var vertexShader = gl.createShader(gl.VERTEX_SHADER); +gl.shaderSource(vertexShader, vertexSource); +gl.compileShader(vertexShader); +if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { + console.log("failed to load shader", " ", gl.getShaderInfoLog(vertexShader)); +} +var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); +gl.shaderSource(fragmentShader, fragmentSource); +gl.compileShader(fragmentShader); +if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { + console.log("failed to load shader", " ", gl.getShaderInfoLog(fragmentShader)); +} +var program = gl.createProgram(); +gl.attachShader(program, vertexShader); +gl.attachShader(program, fragmentShader); +gl.linkProgram(program); + +if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + console.log("linker failed", " ", gl.getProgramInfoLog(program)); +} + +// look up where the vertex data needs to go. +var positionAttributeLocation = gl.getAttribLocation(program, "a_position"); +// look up uniform locations +var resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution"); +var colorUniformLocation = gl.getUniformLocation(program, "u_color"); +// Create a buffer to put three 2d clip space points in +var positionBuffer = gl.createBuffer(); +// Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer) +gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); + +// Tell WebGL how to convert from clip space to pixels +gl.viewport(0, 0, canvas.width, canvas.height); +// Clear the canvas +gl.clearColor(0, 0, 0, 0); +gl.clear(gl.COLOR_BUFFER_BIT); +// Tell it to use our program (pair of shaders) +gl.useProgram(program); +// Turn on the attribute +gl.enableVertexAttribArray(positionAttributeLocation); +// Bind the position buffer. +gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); +// Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER) +var size = 2; // 2 components per iteration +var type = gl.FLOAT; // the data is 32bit floats +var normalize = false; // don't normalize the data +var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position +var offset = 0; // start at the beginning of the buffer +gl.vertexAttribPointer(positionAttributeLocation, size, type, normalize, stride, offset) +// set the resolution +gl.uniform2f(resolutionUniformLocation, gl.canvas.width, gl.canvas.height); +// draw 50 random rectangles in random colors +for (var ii = 0; ii < 50; ++ii) { + // Setup a random rectangle + // This will write to positionBuffer because + // its the last thing we bound on the ARRAY_BUFFER + // bind point +// setRectangle(gl, randomInt(300), randomInt(300), randomInt(300), randomInt(300)); + setRectangle(gl, ii%10*100+10, ii/10*100+10, 100, 100); + // Set a random color. +// gl.uniform4f(colorUniformLocation, Math.random(), Math.random(), Math.random(), 1); + gl.uniform4f(colorUniformLocation, (ii/10)*0.1+(ii%10)*0.01, (ii/10)*0.1+(ii%10)*0.2, (ii%10)*0.1, 1); + // Draw the rectangle. + var primitiveType = gl.TRIANGLES; + var offset = 0; + var count = 6; + gl.drawArrays(primitiveType, offset, count); +} + +// Returns a random integer from 0 to range - 1. +function randomInt(range) { + return Math.floor(Math.random() * range); +} +// Fill the buffer with the values that define a rectangle. +function setRectangle(gl, x, y, width, height) { + var x1 = x; + var x2 = x + width; + var y1 = y; + var y2 = y + height; + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ + x1, y1, + x2, y1, + x1, y2, + x1, y2, + x2, y1, + x2, y2, + ]), gl.STATIC_DRAW); + } + + +var stream = canvas.createPNGStream(); +stream.on('data', function (chunk) { + out.write(chunk); +}); \ No newline at end of file diff --git a/node/examples/webgl/glscissor.js b/node/examples/webgl/glscissor.js new file mode 100644 index 00000000..064c219a --- /dev/null +++ b/node/examples/webgl/glscissor.js @@ -0,0 +1,25 @@ +const { createCanvas, Image } = require('../../export') +const fs = require('fs') +const path = require('path'); +const out = fs.createWriteStream(path.join(__dirname, "..","..")+ '/scissor.png'); + +const canvas = createCanvas(400, 400); +var gl = canvas.getContext("webgl"); + + +gl.enable(gl.SCISSOR_TEST); +gl.scissor(0, 0, canvas.width, canvas.height); +gl.clearColor(1.0, 0.5, 0.5, 1.0); +gl.clear(gl.COLOR_BUFFER_BIT); +gl.finish(); + + +gl.scissor(60, 60, 60, 60); +var color = [0.0,0.5,0.0,1.0]; +gl.clearColor(color[0], color[1], color[2], color[3]); +gl.clear(gl.COLOR_BUFFER_BIT); + +var stream = canvas.createPNGStream(); +stream.on('data', function (chunk) { + out.write(chunk); +}); \ No newline at end of file diff --git a/node/examples/webgl/glstencil.js b/node/examples/webgl/glstencil.js new file mode 100644 index 00000000..0ccd1a07 --- /dev/null +++ b/node/examples/webgl/glstencil.js @@ -0,0 +1,211 @@ +const { createCanvas, Image } = require('../../export') +const fs = require('fs') +const path = require('path'); + +const out = fs.createWriteStream(path.join(__dirname, "..","..")+ '/stencil.png'); +const canvas = createCanvas(600, 600); +var gl = canvas.getContext("webgl"); +var width; +var height; +var program = null; +var program2 = null; +var samplerUniform = null; +var maskTexture; + +var shader_fs_2 = "precision highp float;\ +varying vec2 vTextureCoord;\ +uniform sampler2D uSampler;\ +void main(void) {\ + gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));\ + if (gl_FragColor.a == 0.0) {\ + discard;\ + }\ +}" + +var shader_vs_2 = "precision highp float;\ +attribute vec3 aPos;\ +attribute vec2 aTextureCoords;\ +varying vec2 vTextureCoord;\ +void main(void){\ + gl_Position = vec4(aPos, 1.0);\ + vTextureCoord = aTextureCoords;\ +}" + +var shader_vs = "precision highp float;\ +attribute vec3 aPos;\ +attribute vec4 aColor;\ +varying vec4 vColor;\ +void main(void){\ + gl_Position = vec4(aPos, 1);\ + vColor = aColor;\ +}" + +var shader_fs = "precision highp float;\ +varying vec4 vColor;\ +void main(void) {\ + gl_FragColor = vColor;\ +}" + +function getGLContext() { + if (gl) { + gl.clearColor(74 / 255, 115 / 255, 94 / 255, 1.0); + gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); + gl.viewport(0, 0, canvas.width, canvas.height); + gl.enable(gl.STENCIL_TEST); + } +} + +function initShaders(vs_source, fs_source) { + //compile shaders + var vertexShader = makeShader(vs_source, gl.VERTEX_SHADER); + var fragmentShader = makeShader(fs_source, gl.FRAGMENT_SHADER); + + //create program + var glProgram = gl.createProgram(); + + //attach and link shaders to the program + gl.attachShader(glProgram, vertexShader); + gl.attachShader(glProgram, fragmentShader); + gl.linkProgram(glProgram); + + if (!gl.getProgramParameter(glProgram, gl.LINK_STATUS)) { + alert("Unable to initialize the shader program."); + } + + //use program + // gl.useProgram(glProgram); + return glProgram; +} + +function makeShader(src, type) { + //compile the vertex shader + var shader = gl.createShader(type); + gl.shaderSource(shader, src); + gl.compileShader(shader); + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + alert("Error compiling shader: " + gl.getShaderInfoLog(shader)); + } + return shader; +} +// vertex representing the triangle +var vertex = [ + -.5, -.2, 0, + .5, -.2, 0, + 0, .6, 0 +]; +var stencilVertex = [ + -.2, -.5, 0, + .4, -.5, 0, + .3, .6, 0 +]; +function setupBufferAndDraw() { + // draw the mask image as stencil + gl.useProgram(program2); + var maskVertex = [ + -1, -1, 0, + 1, -1, 0, + 1, 1, 0, + -1, -1, 0, + 1, 1, 0, + -1, 1, 0 + ]; + var maskTexCoords = [ + 0, 0, + 1, 0, + 1, 1, + 0, 0, + 1, 1, + 0, 1 + ]; + var maskBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, maskBuffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(maskVertex), gl.STATIC_DRAW); + + var aMaskVertexPosition = gl.getAttribLocation(program2, 'aPos'); + gl.vertexAttribPointer(aMaskVertexPosition, 3, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(aMaskVertexPosition); + + // texture coordinate data + var maskTexCoordBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, maskTexCoordBuffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(maskTexCoords), gl.STATIC_DRAW); + + var vertexTexCoordAttribute = gl.getAttribLocation(program2, "aTextureCoords"); + gl.enableVertexAttribArray(vertexTexCoordAttribute); + gl.vertexAttribPointer(vertexTexCoordAttribute, 2, gl.FLOAT, false, 0, 0); + + // Always pass test + gl.stencilFunc(gl.ALWAYS, 1, 0xff); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE); + gl.stencilMask(0xff); + gl.clear(gl.STENCIL_BUFFER_BIT); + // No need to display the triangle + gl.colorMask(0, 0, 0, 0); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, maskTexture); + gl.uniform1i(samplerUniform, 0); + + gl.drawArrays(gl.TRIANGLES, 0, maskVertex.length / 3); + // return; + gl.useProgram(program); + // Pass test if stencil value is 1 + gl.stencilFunc(gl.EQUAL, 1, 0xFF); + gl.stencilMask(0x00); + gl.colorMask(1, 1, 1, 1); + // draw the clipped triangle + var color = [ + 1, 0, 0, 1, + 0, 1, 0, 1, + 0, 0, 1, 1 + ]; + var colorBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(color), gl.STATIC_DRAW); + + var aColorPosition = gl.getAttribLocation(program, 'aColor'); + gl.vertexAttribPointer(aColorPosition, 4, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(aColorPosition); + + var vertexBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertex), gl.STATIC_DRAW); + + var aVertexPosition = gl.getAttribLocation(program, 'aPos'); + gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(aVertexPosition); + gl.clear(gl.COLOR_BUFFER_BIT); + gl.drawArrays(gl.TRIANGLES, 0, vertex.length / 3); +} + +function createTexture(source) { + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source); + gl.bindTexture(gl.TEXTURE_2D, null); + return texture; +} + +height = canvas.height; +width = canvas.width; + +getGLContext(); +program = initShaders(shader_vs, shader_fs); +program2 = initShaders(shader_vs_2, shader_fs_2); +samplerUniform = gl.getUniformLocation(program2, 'uSampler'); + +var img = new Image(); +img.onload = function() { + maskTexture = createTexture(img); + setupBufferAndDraw(); + var stream = canvas.createPNGStream(); + stream.on('data', function (chunk) { + out.write(chunk); + }); +}; +img.crossOrigin = ""; +img.src = 'https://img.alicdn.com/tfs/TB1edrqL7Y2gK0jSZFgXXc5OFXa-128-128.png'; \ No newline at end of file diff --git a/node/examples/webgl/gltexture.js b/node/examples/webgl/gltexture.js new file mode 100644 index 00000000..1cb9be14 --- /dev/null +++ b/node/examples/webgl/gltexture.js @@ -0,0 +1,155 @@ +const { createCanvas, Image } = require('../../export') +const fs = require('fs') +const path = require('path'); + +const out = fs.createWriteStream(path.join(__dirname, "..","..")+ '/texture.png'); +const canvas = createCanvas(900, 900); +var gl = canvas.getContext("webgl"); + + +function setRectangle(gl, x, y, width, height) { + var x1 = x; + var x2 = x + width; + var y1 = y; + var y2 = y + height; + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ + x1, y1, + x2, y1, + x1, y2, + x1, y2, + x2, y1, + x2, y2, + ]), gl.STATIC_DRAW); +} + +function drawImage(gl, canvas, image) { + + var fragmentShaderStr = "precision mediump float;" + + "uniform sampler2D u_image;" + + "varying vec2 v_texCoord;" + + "void main() {" + + "gl_FragColor = texture2D(u_image, v_texCoord);" + + "}"; + var vertexShaderStr = "attribute vec2 a_position;" + + "attribute vec2 a_texCoord;" + + "uniform vec2 u_resolution;" + + "varying vec2 v_texCoord;" + + "void main() {" + + "vec2 zeroToOne = a_position / u_resolution;" + + "vec2 zeroToTwo = zeroToOne * 2.0;" + + "vec2 clipSpace = zeroToTwo - 1.0;" + + "gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);" + + "v_texCoord = a_texCoord;" + + "}"; + var vertexShader = gl.createShader(gl.VERTEX_SHADER); + gl.shaderSource(vertexShader, vertexShaderStr); + gl.compileShader(vertexShader); + + var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); + gl.shaderSource(fragmentShader, fragmentShaderStr); + gl.compileShader(fragmentShader); + + var program = gl.createProgram(); + gl.attachShader(program, vertexShader); + gl.attachShader(program, fragmentShader); + + // gl.bindAttribLocation(gl.program, v3PositionIndex, "a_position"); + gl.linkProgram(program); + + // var samplerIndex = gl.getUniformLocation(gl.program, "a_texCoord"); + // gl.useProgram(gl.program); + + var positionLocation = gl.getAttribLocation(program, "a_position"); + var texcoordLocation = gl.getAttribLocation(program, "a_texCoord"); + + var positionBuffer = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); + setRectangle(gl, 0, 0, image.width, image.height); + + var texcoordBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ + 0.0, 0.0, + 1.0, 0.0, + 0.0, 1.0, + 0.0, 1.0, + 1.0, 0.0, + 1.0, 1.0, + ]), gl.STATIC_DRAW); + + // Create a texture. + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + + // Set the parameters so we can render any size image. + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + + // Upload the image into the texture. + console.log(`the gl.RGBA is ${gl.RGBA}`) + console.log(`TEXTURE_2D is ${gl.TEXTURE_2D}`) + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); + + // lookup uniforms + var resolutionLocation = gl.getUniformLocation(program, "u_resolution"); + // Tell WebGL how to convert from clip space to pixels + gl.viewport(0, 0, canvas.width, canvas.height); + // + // // Clear the canvas + gl.clearColor(0.0, 0.2, 0.0, 0.3); + gl.clear(gl.COLOR_BUFFER_BIT); + // + // // Tell it to use our program (pair of shaders) + gl.useProgram(program); + // + // // Turn on the position attribute + gl.enableVertexAttribArray(positionLocation); + // + // // Bind the position buffer. + gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); + // + // // Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER) + // Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER) + var size = 2; // 2 components per iteration + var type = gl.FLOAT; // the data is 32bit floats + var normalize = false; // don't normalize the data + var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position + var offset = 0; // start at the beginning of the buffer + gl.vertexAttribPointer(positionLocation, size, type, normalize, stride, offset) + + // Turn on the teccord attribute + gl.enableVertexAttribArray(texcoordLocation); + + // Bind the position buffer. + gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer); + + // Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER) + var size = 2; // 2 components per iteration + var type = gl.FLOAT; // the data is 32bit floats + var normalize = false; // don't normalize the data + var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position + var offset = 0; // start at the beginning of the buffer + gl.vertexAttribPointer(texcoordLocation, size, type, normalize, stride, offset) + + // set the resolution + gl.uniform2f(resolutionLocation, canvas.width, canvas.height); + + // Draw the rectangle. + var primitiveType = gl.TRIANGLES; + var offset = 0; + var count = 6; + gl.drawArrays(primitiveType, offset, count); +} + +var image = new Image(); +image.onload = function () { + drawImage(gl, canvas, image); + var stream = canvas.createPNGStream(); + stream.on('data', function (chunk) { + out.write(chunk); + }); +} +image.src = "https://img.alicdn.com/tfs/TB1FQDkCEz1gK0jSZLeXXb9kVXa-1200-807.jpg"; diff --git a/node/examples/webgl/gltriangle.js b/node/examples/webgl/gltriangle.js new file mode 100644 index 00000000..7e87b4c4 --- /dev/null +++ b/node/examples/webgl/gltriangle.js @@ -0,0 +1,89 @@ +const { createCanvas, Image } = require('../../export') +const fs = require('fs') +const path = require('path'); + +const out = fs.createWriteStream(path.join(__dirname, "..","..")+ '/triangle.png'); +const canvas = createCanvas(400, 400); +const gl = canvas.getContext('webgl') + +function draw() { + + var vertices = [ + -1.0,-1.0,0.0, + -1.0,1.0,0.0, + 1.0,1.0,0.0, + ]; + + var indices = [0,1,2]; + + var vertex_buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); + + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, null); + + var Index_Buffer = gl.createBuffer(); + + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Index_Buffer); + + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); + + + var vertCode = + "attribute vec4 vPosition;\n"+ + "void main()\n"+ + "{\n"+ + " gl_Position = vPosition;\n"+ + "}\n"; + var vertShader = gl.createShader(gl.VERTEX_SHADER); + + gl.shaderSource(vertShader, vertCode); + + + gl.compileShader(vertShader); + + var fragCode ="void main()\n"+ + "{\n"+ + " gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\n"+ + "}\n"; + + var fragShader = gl.createShader(gl.FRAGMENT_SHADER); + gl.shaderSource(fragShader, fragCode); + + + gl.compileShader(fragShader); + + var shaderProgram = gl.createProgram(); + + gl.attachShader(shaderProgram, vertShader); + + gl.attachShader(shaderProgram, fragShader); + + gl.linkProgram(shaderProgram); + gl.useProgram(shaderProgram); + + + gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Index_Buffer); + + var coord = gl.getAttribLocation(shaderProgram, "vPosition"); + gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(coord); + gl.enable(gl.DEPTH_TEST); + gl.viewport(0,0, canvas.width, canvas.height); + gl.clearColor(1, 0.5, 0.4, 1.0); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + + gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0); + +} + +draw(); + + var stream = canvas.createPNGStream(); +stream.on('data', function (chunk) { + out.write(chunk); +}); \ No newline at end of file diff --git a/node/examples/webgl/gltriangle2.js b/node/examples/webgl/gltriangle2.js new file mode 100644 index 00000000..baf2f96e --- /dev/null +++ b/node/examples/webgl/gltriangle2.js @@ -0,0 +1,64 @@ +const { createCanvas, Image } = require('../../export') +const fs = require('fs') +const path = require('path'); +const out = fs.createWriteStream(path.join(__dirname, "..","..")+ '/triangle2.png'); + + +const canvas = createCanvas(400, 400); +const gl = canvas.getContext('webgl') + +function draw() { + + function initShaders(e, r, a) { var t = createProgram(e, r, a); return t ? (e.useProgram(t), e.program = t, !0) : (console.log("Failed to create program"), !1) } function createProgram(e, r, a) { var t = loadShader(e, e.VERTEX_SHADER, r), o = loadShader(e, e.FRAGMENT_SHADER, a); if (!t || !o) return null; var l = e.createProgram(); if (!l) return null; if (e.attachShader(l, t), e.attachShader(l, o), e.linkProgram(l), !e.getProgramParameter(l, e.LINK_STATUS)) { var n = e.getProgramInfoLog(l); return console.log("Failed to link program: " + n), e.deleteProgram(l), e.deleteShader(o), e.deleteShader(t), null } return l } function loadShader(e, r, a) { var t = e.createShader(r); if (null == t) return console.log("unable to create shader"), null; if (e.shaderSource(t, a), e.compileShader(t), !e.getShaderParameter(t, e.COMPILE_STATUS)) { var o = e.getShaderInfoLog(t); return console.log("Failed to compile shader: " + o), e.deleteShader(t), null } return t } function getWebGLContext(e, r) { var a = WebGLUtils.setupWebGL(e); return a ? ((arguments.length < 2 || r) && (a = WebGLDebugUtils.makeDebugContext(a)), a) : null } + + function init(VSHADER_SOURCE, FSHADER_SOURCE) { + if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) { + console.log("Failed to init the shaders "); + return; + } + + + let vertices = new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]); + let n = 3; + let vertexBuffer = gl.createBuffer(); + if (!vertexBuffer) { + console.log("Failed to create buffer\n"); + } + gl.viewport(0,0,canvas.width,canvas.height); + gl.clearColor(0.0, 0.0, 1.0, 1.0); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); + + let a_Position = gl.getAttribLocation(gl.program, 'a_Position'); + gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(a_Position); + + let u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor'); + gl.uniform4f(u_FragColor, 1.0, 1.0, 0.0, 1.0); + + gl.drawArrays(gl.TRIANGLES, 0, n); + + } + let vertexShader="attribute vec4 a_Position; \n"+ + "void main(){ \n"+ + "gl_Position=a_Position;\n"+ + "}\n"; + + let fragmentShader= + "precision mediump float; \n"+ + "uniform vec4 u_FragColor; \n"+ + "void main(){\n"+ + "gl_FragColor=u_FragColor;\n"+ + "}\n"; + + init(vertexShader,fragmentShader); + +} + +draw(); + + var stream = canvas.createPNGStream(); +stream.on('data', function (chunk) { + out.write(chunk); +}); \ No newline at end of file diff --git a/node/export.js b/node/export.js index cdf1ead1..7b8c3d55 100644 --- a/node/export.js +++ b/node/export.js @@ -6,7 +6,7 @@ * For the full copyright and license information, please view * the LICENSE file in the root directory of this source tree. */ -const { createCanvas ,Image, createImage} = require('bindings')('canvas'); +const { createCanvas , createImage} = require('bindings')('canvas'); const { PNGStream } = require("./stream/pngstream"); const { JPGStream } = require('./stream/jpgstream') module.exports = { @@ -30,5 +30,3 @@ function createCanvasInner(width, height) { - - diff --git a/node/renderContext/GRenderContext.h b/node/renderContext/GRenderContext.h deleted file mode 100644 index 650b22dd..00000000 --- a/node/renderContext/GRenderContext.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Created by G-Canvas Open Source Team. - * Copyright (c) 2017, Alibaba, Inc. All rights reserved. - * - * This source code is licensed under the Apache Licence 2.0. - * For the full copyright and license information, please view - * the LICENSE file in the root directory of this source tree. - */ -#define CONTEXT_ES20 -#ifndef GBACKEND_H -#define GBACKEND_H -#include -#include -#include "lodepng.h" -#include -#include -#include -#include "GConvert.h" -#include "NodeBindingUtil.h" -#include "Util.h" -#include "GFrameBufferObject.h" - -namespace NodeBinding -{ -extern void encodePixelsToPNGFile(std::string filename, uint8_t *buffer, int width, int height); -extern void decodeFile2Pixels(std::string filename, std::vector &image); -extern void encodePixelsToJPEGFile(std::string filename, uint8_t *buffer, int width, int height); -extern void encodePNGInBuffer(std::vector &in,unsigned char *data,int width,int height); -extern void encodeJPEGInBuffer(unsigned char **in,unsigned long &size,unsigned char *data,int width,int height); -class GRenderContext -{ -public: - GRenderContext() : mWidth(0), mHeight(0), mCanvas(nullptr) - { - - } - GRenderContext(int width, int height); - GRenderContext(int width, int height, int ratio); - virtual ~GRenderContext(); - void initRenderEnviroment(); - void render2file(std::string caseName,PIC_FORMAT format); - void drawFrame(); - GCanvasContext *getCtx() { return mCanvas->GetGCanvasContext(); } - int inline getWdith() { return this->mWidth; } - int inline getHeight() { return this->mHeight; } - void destoryRenderEnviroment(); - void recordTextures(int textureId); - void recordImageTexture(std::string url,int textureId); - int getTextureIdByUrl(std::string url); - void BindFBO(); - void makeCurrent(); - int getImagePixelPNG(std::vector &in); - int getImagePixelJPG(unsigned char **data,unsigned long &size); - int readPixelAndSampleFromCurrentCtx(unsigned char *data); -private: - std::shared_ptr mCanvas; - void initCanvas(); - int mHeight; - int mWidth; - int mCanvasHeight; - int mCanvasWidth; - int mRatio; - int drawCount = 0; - EGLDisplay mEglDisplay; - EGLSurface mEglSurface; - EGLContext mEglContext; - GLuint mFboIdSrc = 0; - GLuint mRenderBufferIdSrc = 0; - GLuint mDepthRenderbufferIdSrc = 0; - std::vector textures; - std::unordered_map imageTextureMap; - static void InitSharedContextIfNot(); - GLuint createFBO(int fboWidth,int fboHeigh,GLuint *renderBufferId,GLuint *depthBufferId); - GLuint mFboIdDes=0; - GLuint mRenderBufferIdDes=0; - GLuint mDepthRenderbufferIdDes=0; - -}; -} // namespace NodeBinding - -#endif \ No newline at end of file diff --git a/node/temp_dir/cube.png b/node/temp_dir/cube.png new file mode 100644 index 00000000..287a6239 Binary files /dev/null and b/node/temp_dir/cube.png differ diff --git a/node/temp_dir/cube2.png b/node/temp_dir/cube2.png new file mode 100644 index 00000000..8ebdbb0b Binary files /dev/null and b/node/temp_dir/cube2.png differ diff --git a/node/temp_dir/cubeWebGL.png b/node/temp_dir/cubeWebGL.png new file mode 100644 index 00000000..287a6239 Binary files /dev/null and b/node/temp_dir/cubeWebGL.png differ diff --git a/node/temp_dir/distacenField.png b/node/temp_dir/distacenField.png new file mode 100644 index 00000000..7fee7ff0 Binary files /dev/null and b/node/temp_dir/distacenField.png differ diff --git a/node/temp_dir/gltexture.png b/node/temp_dir/gltexture.png new file mode 100644 index 00000000..64799801 Binary files /dev/null and b/node/temp_dir/gltexture.png differ diff --git a/node/temp_dir/stencil.png b/node/temp_dir/stencil.png new file mode 100644 index 00000000..cee4bac6 Binary files /dev/null and b/node/temp_dir/stencil.png differ diff --git a/node/temp_dir/triagnleWebGL.png b/node/temp_dir/triagnleWebGL.png new file mode 100644 index 00000000..f497ffc4 Binary files /dev/null and b/node/temp_dir/triagnleWebGL.png differ diff --git a/node/temp_dir/triagnleWebGL2.png b/node/temp_dir/triagnleWebGL2.png new file mode 100644 index 00000000..9759e282 Binary files /dev/null and b/node/temp_dir/triagnleWebGL2.png differ