lwjgl not drawing vertex buffer - lwjgl

Im try to get a super simple lwjgl app going that draws a simple triangle, but cant find the right order of calls to make anything meaningful appear. im using a simple vertex buffer and no shaders.
for some reason each frame is a white triangle on the lower right side of the frame, regardless of what is in the actual vertex buffer.
public void run() {
GLFWErrorCallback.createThrow().set();
glfwInit();
glfwDefaultWindowHints();
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
long h_window = glfwCreateWindow(640, 480, "test", 0, 0);
glfwShowWindow(h_window);
glfwMakeContextCurrent(h_window);
GL.createCapabilities();
glEnableClientState(GL_VERTEX_ARRAY);
int b_vertex = glGenBuffers();
float[] vertex = {
0,0,0,
0,0,0,
0,0,0
};
glBindBuffer(GL_ARRAY_BUFFER, b_vertex);
glBufferData(GL_ARRAY_BUFFER, vertex, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
while (!glfwWindowShouldClose(h_window)) {
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, b_vertex);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0L);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glfwSwapBuffers(h_window);
glfwWaitEventsTimeout(1f / 30f);
}
}
im definitely missing something, but have no idea what it is. here is what this shows:
Screenshot of Running app

Found the problem.
glVertexPointer(3, GL_FLOAT, 0, 0L);
is for shaderless buffer descriptions
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0L);
is for buffer descriptions that also bind buffers to shader inputs

Related

How can I replace color shader with texture in WebGL?

I have to implement these options with WebGL. I'm currently getting the following error: "WebGL: INVALID_OPERATION: drawArrays: attempt to access out of bounds arrays". However, my question isn't just about that. I wan't to know if I'm doing it the right way in general.
I believe the following code is the critical part I'm not doing right. What we are trying to do is load with a color shader and only when a texture is loaded, the texture replaces the color shader.
I'm new to this topic, please help! I'll be updating with any further details you may need.
function renderScene() {
gl.viewport(pgl.viewport.x, pgl.viewport.y, pgl.viewport.width, pgl.viewport.height);
gl.clear(gl.COLOR_BUFFER_BIT);
var modelViewMatrix = mat4.create();
mat4.multiply(modelViewMatrix, viewMatrix, modelMatrix);
gl.useProgram(pgl.shaderProgram);
gl.uniformMatrix4fv(pgl.shaderProgram.uModelViewMatrix, false, modelViewMatrix);
gl.uniformMatrix4fv(pgl.shaderProgram.uProjMatrix, false, projMatrix);
gl.enableVertexAttribArray(pgl.shaderProgram.aPosition);
gl.bindBuffer(gl.ARRAY_BUFFER, pgl.vbo);
gl.vertexAttribPointer(pgl.shaderProgram.aPosition, 3, gl.FLOAT, false, 0, 0);
if (isColor) {
gl.enableVertexAttribArray(pgl.shaderProgram.aColor);
gl.bindBuffer(gl.ARRAY_BUFFER, pgl.vboColor);
gl.vertexAttribPointer(pgl.shaderProgram.aColor, 4, gl.FLOAT, false, 0, 0);
} else {
gl.disableVertexAttribArray(pgl.shaderProgram.aColor);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.enableVertexAttribArray(pgl.shaderProgram.aTexture);
gl.bindBuffer(gl.ARRAY_BUFFER, pgl.vboTexture);
gl.vertexAttribPointer(pgl.shaderProgram.aTexture, 2, gl.FLOAT, false, 0, 0);
gl.uniform1i(pgl.shaderProgram.uSampler, 0);
}
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3);
requestAnimationFrame(renderScene);
updateScene();
}
This is the UI
(Pastebin.com) Here's the complete code I'm working on... sorry if it's a mess.

Cocos2dx: Sprite3D won't render to texture

I use RenderTexture to render a layer with all its nodes to a texture then apply an OpenGL shader on that texture to create post-process effects. It works all fine except with Sprite3D and Billboard nodes. It has been asked on their forums a few times without any response. I wonder if anyone got this to work.
Here is an example:
Layer* gameLayer = Layer::create();
this->addChild(gameLayer, 0);
auto dir = Director::getInstance()->getWinSize();
Camera *camera = Camera::createPerspective(60, (GLfloat)dir.width / dir.height, 1, 1000);
camera->setPosition3D(Vec3(0, 100, 100));
camera->lookAt(Vec3(0, 0, 0), Vec3(0, 1, 0));
gameLayer->addChild(camera); //add camera to the scene
// You'll get a NULL camera inside BillBoard::calculateBillbaordTransform() function
// if you call visit()
/*auto billboard = BillBoard::create("cocos2d-x.png", BillBoard::Mode::VIEW_POINT_ORIENTED);
billboard->setPosition(Vec2(VisibleRect::center().x, VisibleRect::center().y));
gameLayer->addChild(billboard, 100);*/
// This one won't render into the texture
Sprite3D* sprite3D = Sprite3D::create("blend_test/character_3_animations_test.c3b");
sprite3D->setScale(5.0f); //sets the object scale in float
sprite3D->setRotation3D(Vec3(0.0f, 0.0f, 0.0f));
//sprite3D->setPosition3D(Vec3(VisibleRect::center().x, VisibleRect::center().y, 0.0f)); //sets sprite position
sprite3D->setPosition(Vec2(VisibleRect::center().x, VisibleRect::center().y));
gameLayer->addChild(sprite3D, 1); //adds sprite to scene, z-index: 1
// This one works just fine and appears black and white as expected
// in the resulting texture
Sprite* sprite2D = Sprite::create("cocos2d-x.png");
sprite2D->setPosition(Vec2(VisibleRect::center().x, VisibleRect::center().y));
gameLayer->addChild(sprite2D);
// Black and white OpenGL shader
GLProgram* glProgram = GLProgram::createWithFilenames("shaders/gray.vert", "shaders/gray.frag");
glProgram->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::VERTEX_ATTRIB_POSITION);
glProgram->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_COLOR);
glProgram->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORD);
glProgram->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD1, GLProgram::VERTEX_ATTRIB_TEX_COORD1);
glProgram->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD2, GLProgram::VERTEX_ATTRIB_TEX_COORD2);
glProgram->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD3, GLProgram::VERTEX_ATTRIB_TEX_COORD3);
glProgram->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_NORMAL, GLProgram::VERTEX_ATTRIB_NORMAL);
glProgram->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_BLEND_WEIGHT, GLProgram::VERTEX_ATTRIB_BLEND_WEIGHT);
glProgram->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_BLEND_INDEX, GLProgram::VERTEX_ATTRIB_BLEND_INDEX);
glProgram->link();
glProgram->updateUniforms();
RenderTexture* renderTexture = RenderTexture::create(VisibleRect::width(), VisibleRect::height());
renderTexture->retain();
Sprite* ppSprite = Sprite::createWithTexture(renderTexture->getSprite()->getTexture());
ppSprite->setTextureRect(Rect(0, 0, ppSprite->getTexture()->getContentSize().width,
ppSprite->getTexture()->getContentSize().height));
ppSprite->setAnchorPoint(Point::ZERO);
ppSprite->setPosition(Point::ZERO);
ppSprite->setFlippedY(true);
ppSprite->setGLProgram(glProgram);
this->addChild(ppSprite, 100);
renderTexture->beginWithClear(0.0f, 0.0f, 0.0f, 0.0f);
auto renderer = _director->getRenderer();
auto& parentTransform = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
gameLayer->visit(renderer, parentTransform, true);
//gameLayer->visit();
renderTexture->end();
ppSprite->setTexture(renderTexture->getSprite()->getTexture());
Cocos2d-x v3.11.1 (current as of this post) and below don't properly support RenderTextures with Sprite3D because of a clear depth buffer bug.
There is a GitHub issue on the bug. But a workaround now exists:
...
sprite3D->setForce2DQueue(true); // puts your Sprite3D on same render queue as the RenderTexture. More info below.
...
auto rt = RenderTexture::create(1280, 720, Texture2D::PixelFormat::RGBA8888, GL_DEPTH24_STENCIL8); // By default a depth buffer isn't created
rt->setKeepMatrix(true); // required
...
...
rt->beginWithClear(0, 0, 0, 0, 1); // required, clears the depth buffer
Also, changes need to be made to RenderTexture.cpp. This fixes the clear depth buffer bug in Cocos2d-x.
void RenderTexture::onClear()
{
// save clear color
GLfloat oldClearColor[4] = {0.0f};
GLfloat oldDepthClearValue = 0.0f;
GLint oldStencilClearValue = 0;
GLboolean oldDepthWrite = GL_FALSE;
// backup and set
if (_clearFlags & GL_COLOR_BUFFER_BIT)
{
glGetFloatv(GL_COLOR_CLEAR_VALUE, oldClearColor);
glClearColor(_clearColor.r, _clearColor.g, _clearColor.b, _clearColor.a);
}
if (_clearFlags & GL_DEPTH_BUFFER_BIT)
{
glGetFloatv(GL_DEPTH_CLEAR_VALUE, &oldDepthClearValue);
glClearDepth(_clearDepth);
glGetBooleanv(GL_DEPTH_WRITEMASK, &oldDepthWrite);
glDepthMask(true);
}
if (_clearFlags & GL_STENCIL_BUFFER_BIT)
{
glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &oldStencilClearValue);
glClearStencil(_clearStencil);
}
// clear
glClear(_clearFlags);
// restore
if (_clearFlags & GL_COLOR_BUFFER_BIT)
{
glClearColor(oldClearColor[0], oldClearColor[1], oldClearColor[2], oldClearColor[3]);
}
if (_clearFlags & GL_DEPTH_BUFFER_BIT)
{
glClearDepth(oldDepthClearValue);
glDepthMask(oldDepthWrite);
}
if (_clearFlags & GL_STENCIL_BUFFER_BIT)
{
glClearStencil(oldStencilClearValue);
}
}
See the issue for more details. I also made an example gist of the workaround. Screenshot below.
I'm not sure about billboards, but this workaround might fix it too.
Info on Cocos2d-x render queues:
The Sprite3D needs to be on the same render queue as the RenderTexture. Cocos2d-x (as of v3.7 or so) now has 5 render queues:
Global Z Order < 0
3D Opaque
3D Transparent
Global Z Order == 0 (default for 2D)
Global Z Order > 0
You can put the Sprite3D and the RenderTexture on the last queue with setGlobalZOrder(1) or just put the Sprite3D in the 2D queue with sprite3D->setForce2DQueue(true).
unlike cocos2d RenderTexture the following worked fine for 3D screen capture (or anything i imagine)!
Sprite * CcGlobal::getScreenAsSprite(void) {
Size screenSize = Director::getInstance()->getWinSize();
int width = screenSize.width;
int height = screenSize.height;
std::shared_ptr<GLubyte> buffer(new GLubyte[width * height * 4], [](GLubyte* p) { CC_SAFE_DELETE_ARRAY(p); });
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer.get());
Image* image = new (std::nothrow) Image;
image->initWithRawData(buffer.get(), width * height * 4, width, height, 8);
Texture2D *texture = new (std::nothrow) Texture2D();
texture->initWithImage(image);
SpriteFrame *spriteFrame = SpriteFrame::createWithTexture(texture, Rect(Vec2(0, 0), screenSize));
Sprite *sprite = Sprite::createWithSpriteFrame(spriteFrame);
sprite->setFlippedY(true);
delete image;
return sprite;
}
===================================================

LibGDX FrameBuffer

I'm trying to make a game where you build a spaceship from parts, and fly it around and such.
I would like to create the ship from a series of components (from a TextureAtlas for instance). I'd like to draw the ship from it's component textures, and then save the drawn ship as one large Texture. (So i don't have to draw 50 component textures, just one ship texture. What would be the best way to go about this?
I've been trying to do so using a FrameBuffer. I've been able to draw the components to a Texture, and draw the texture to the screen, but no matter what I try the Texture ends up with a solid background the size of the frame buffer. It's like the clear command can't clear with transparency. Here's the drawing code I have at the moment. The ship is just a Sprite which i save the FrameBuffer texture to.
public void render(){
if (ship == null){
int screenwidth = Gdx.graphics.getWidth();
int screenheight = Gdx.graphics.getHeight();
SpriteBatch fb = new SpriteBatch();
FrameBuffer fbo = new FrameBuffer(Format.RGB888, screenwidth, screenheight, false);
fbo.begin();
fb.enableBlending();
Gdx.gl.glBlendFuncSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);
Gdx.gl.glClearColor(1, 0, 1, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
fb.begin();
atlas.createSprite("0").draw(fb);
fb.end();
fbo.end();
ship = new Sprite(fbo.getColorBufferTexture());
ship.setPosition(0, -screenheight);
}
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.enableBlending();
batch.setBlendFunction(GL20.GL_ONE, GL20.GL_ZERO);
ship.draw(batch);
batch.end();
}
The problem here lies in this line:
FrameBuffer fbo = new FrameBuffer(Format.RGB888, screenwidth, screenheight, false);
specifically with Format.RGB888. This line is saying that your FrameBuffer should be Red (8 bits) followed by Green (8 bits) followed by Blue (8 bits). Notice however, that this format doesn't have any bits for Alpha (transparency). In order to get transparency out of your frame buffer, you probably instead want to use the Format.RGBA8888, which includes an additional 8 bits for Alpha.
Hope this helps.

Texture from Texture Atlas Find Region or Create Sprite

I am trying to get the Texture from Sprite or Atlas Region created by Texture Atlas.
atlas=new TextureAtlas(Gdx.files.internal("Test.pack"));
region=atlas.findRegion("green");
or
Sprite s = atlas.createSprite("red");
texture = s.getTexture();
I have given the name of image in findRegion and createSprite method, it always picks the other image object. I want to get the texture of the image so that part of that texture can be rendered.
Here is the Packer image:
http://i61.tinypic.com/neupo2.png
Even if i try to get green region or red, it always returns blue. Any help would be appreciated.
When you do "textureAtlas.findRegion("objectTexture").getTexture();" (from James Skemp's answer) you're getting the whole texture from the atlas, not just from the region "objectTexture".
Don't bother creating Texture to create the Sprite, you can use the TextureRegion to create the Sprite. Something like this:
atlas=new TextureAtlas(Gdx.files.internal("Test.pack"));
regionGreen=atlas.findRegion("green");
Sprite s = new Sprite(regionGreen);
My use case is slightly different, but I was running into the same issue.
I have an object, which extends Actor, that I want to draw using a region in an atlas.
public class MyObject extends Actor {
private Texture texture;
public MyObject() {
TextureAtlas textureAtlas = new TextureAtlas(Gdx.files.internal("xxx.atlas"));
texture = textureAtlas.findRegion("objectTexture").getTexture();
Gdx.app.log(TAG, "Texture width: " + texture.getWidth());
Gdx.app.log(TAG, "Texture height: " + texture.getHeight());
setBounds(getX(), getY(), Constants.STANDARD_TILE_WIDTH, Constants.STANDARD_TILE_HEIGHT);
// ...
}
#Override
public void draw(Batch batch, float parentAlpha) {
batch.draw(texture,
worldPosition.x * Constants.STANDARD_TILE_WIDTH, worldPosition.y * Constants.STANDARD_TILE_WIDTH,
texture.getWidth(), texture.getHeight());
}
}
Instead of just the region I was expecting I instead received the entire atlas, so my logged texture width and height were 1024 x 128.
Unfortunate, and still not sure why getTexture() returns too much, but switching over to batchDraw(TextureRegion, ...) at least got me in a better place.
public class MyObject extends Actor {
private TextureRegion texture;
public MyObject() {
TextureAtlas textureAtlas = new TextureAtlas(Gdx.files.internal("xxx.atlas"));
texture = textureAtlas.findRegion("objectTexture");
setBounds(getX(), getY(), Constants.STANDARD_TILE_WIDTH, Constants.STANDARD_TILE_HEIGHT);
// ...
}
#Override
public void draw(Batch batch, float parentAlpha) {
batch.draw(texture, getX(), getY());
}
}
Based upon what I saw with my sprites, the questioner was seeing a blue square for the same reason I was; the entire image is getting loaded by getTexture() and since it starts at the bottom left, you're always seeing a blue square.
Using the Sprite(TextureRegion) constructor may have also resolved their issue.
Seems to me your problem is the Test.pack file, not the texture.
It works with this one I packed with GDX Texture Packer:
Test.png
format: RGBA8888
filter: Nearest,Nearest
repeat: none
blue
rotate: false
xy: 1, 1
size: 51, 51
orig: 51, 51
offset: 0, 0
index: -1
green
rotate: false
xy: 54, 1
size: 51, 51
orig: 51, 51
offset: 0, 0
index: -1
red
rotate: false
xy: 107, 1
size: 51, 51
orig: 51, 51
offset: 0, 0
index: -1
yellow
rotate: false
xy: 160, 1
size: 51, 51
orig: 51, 51
offset: 0, 0
index: -1
Use index also to get it.Get the index from pack file or .atlas file.
atlas=new TextureAtlas(Gdx.files.internal("Test.pack"));
region=atlas.findRegion("green",index);
or
Sprite s = atlas.createSprite("red",index);
texture = s.getTexture();

How to continuously fade a BitmapData to a certain color?

I'm drawing stuff on a bitmapData and I need to continuously fade every pixel to 0x808080 while still drawing (its for a DisplacementMapFilter)...
I think this illustrates my problem:
http://www.ventdaval.com/lab/grey.swf
The simpler approach I tried was drawing a semi-transparent grey box on it, but it never reaches a single color (i.e. 0x808081 will never be turned to 0x808080)... The same kind of thing happens with a ColorMatrixFilter trying to progressively reduce the saturation and/or contrast. (the example above is applying a filter with -10 contrast every frame).
I'm trying paletteMap now, and I'm sensing this could be the way to go, but I haven't been able to get it... any ideas?
You can try to fade it slightly more than you are fading it now, so color will go to 0x808080, you just need to do some calculations.
Yes, you can do this with paletteMap.
The third way will be to write PixelBender shader for it.
You can also use your normal fading and do paletteMap or PixelBender one once in a few frames, to speed-up all this.
I think the easiest way to do this would be with two successive color filters. That is:
var n:Number = 0.9;
var off:Number = 0x80;
var filter:ColorMatrixFilter = new ColorMatrixFilter( [
1, 0, 0, 0, -off,
0, 1, 0, 0, -off,
0, 0, 1, 0, -off,
0, 0, 0, 1, -off ] );
var filter2:ColorMatrixFilter = new ColorMatrixFilter( [
n, 0, 0, 0, off,
0, n, 0, 0, off,
0, 0, n, 0, off,
0, 0, 0, n, off ] );
function onFrame( e:Event ) {
myBMD.applyFilter( myBMD, myBMD.rect, new Point(), filter );
myBMD.applyFilter( myBMD, myBMD.rect, new Point(), filter2 );
}
The first filter offsets each channel value downwards by 128 - turning your gray-based image into a black-based image. The second filter multiplies each channel value by the modulator (0.9 in my example), and then offsets the values back up by 128.
I wound up solving this by filling the texture with 0xFF808080 every frame, then drawing my dynamic stuff to a second, transparent bitmap, doing a colortransform on it with a lower alpha multiplier (say 0.98), and then copypixeling that bitmap to the main bitmap with mergealpha on. Works a treat:
public function update():void
{
lock();
fillRect(rect, 0xFF808080);
drawTarget.lock();
drawTarget.colorTransform(rect, fadeTransform);
drawTarget.applyFilter(drawTarget, rect, pt, blurFilter);
drawTarget.unlock();
copyPixels(drawTarget, rect, pt, null, null, true);
unlock();
}