I can't get a SSBO working using Qt3D. I'm also unable to find a single example displaying how it is supposed to be done.
Here are the main parts of my code:
Buffer init:
QByteArray ssboData;
ssboData.resize(1000);
ssboData.fill(0);
mySSBOBuffer = new Qt3DRender::QBuffer(this);
mySSBOBuffer->setUsage(Qt3DRender::QBuffer::DynamicRead);
mySSBOBuffer->setAccessType(Qt3DRender::QBuffer::AccessType::ReadWrite);
mySSBOBuffer->setData(ssboData);
QByteArray atomicCounterData;
atomicCounterData.resize(4);
atomicCounterData.fill(0);
myAtomicCounterBuffer = new Qt3DRender::QBuffer(this);
myAtomicCounterBuffer->setUsage(Qt3DRender::QBuffer::DynamicRead);
myAtomicCounterBuffer->setAccessType(Qt3DRender::QBuffer::AccessType::ReadWrite);
myAtomicCounterBuffer->setData(atomicCounterData);
Passing the buffers as QParameters to the shader.
myMaterial->addParameter(new Qt3DRender::QParameter("acCountFrags", QVariant::fromValue(myAtomicCounterBuffer->id()), myMaterial));
myMaterial->addParameter(new Qt3DRender::QParameter("ssboBuffer", QVariant::fromValue(mySSBOBuffer->id()), myMaterial));
I also tried
myMaterial->addParameter(new Qt3DRender::QParameter("acCountFrags", QVariant::fromValue(myAtomicCounterBuffer), myMaterial));
myMaterial->addParameter(new Qt3DRender::QParameter("ssboBuffer", QVariant::fromValue(mySSBOBuffer), myMaterial));
Fragment Shader (color has no use, just to check shader is working):
#version 430 core
layout(binding = 0, offset = 0) uniform atomic_uint acCountFrags;
layout (std430) buffer ssboBuffer
{
uint fragIds[];
};
out vec4 color;
void main()
{
uint index = atomicCounterIncrement(acCountFrags);
fragIds[index] = 5;
color = vec4(0.2, 0.2, 0.2, 1.0);
}
In all of my tries, nothing is written to the buffers after rendering. They are still full of 0 like after init.
Does anybody know if i'm doing something wrong ? Or somewhere I could find a working example ?
Thank you.
The answer was a missing BufferCapture component in my FrameGraph. Found it thanks to the example given by HappyFeet in the comments.
Related
I just tried to do this
C++
struct PointLight
{
glm::vec4 position;
glm::vec4 colour;
};
std::vector <PointLight> lights_array;
GLSL 320 ES:
layout (std140) struct PointLight
{
vec4 position;
vec4 colour;
};
layout (std140) buffer Lights
{
int count;
PointLight data [];
}
b_lights;
The compile error surprised me:
error C7600: no value specified for layout qualifier 'std140'
I can't find a straight answer but I get the impression that I can't specify std140 for struct definitions. Is this so? Or how can I spell it?
If not, then how am I able to guarantee that I can send lights_array to glBufferData so that it has the correct layout in the shader's b_lights.data array?
In other words, why is std140 required for the buffer but not for the struct?
Interface blocks have layouts, not structs. The layout applies to how the block lays out its elements, recursively, through their entire contents.
So you don't need to apply an interface block layout to a random struct.
I'm stuck trying to render some extremely basic stuff on webgl, I've dumbed down the rendering to the most basic thing I can think of in order to find where the issue lies, but I can't even draw a simple square for some reason. The scene I really want to render is more complex, but as I said, I've dumbed it down to try to find the problem and still no luck. I'm hoping someone can take a look and find whatever I'm missing, wich I assume is a setup step at some point.
The gl commands I'm running (as reported by webgl inspector, without errors) are:
clearColor(0,0,0,1)
clearDepth(1)
clear(COLOR_BUFFER_BIT | DEPTH_BUFFER_BIT)
useProgram([Program 2])
bindBuffer(ARRAY_BUFFER, [Buffer 5])
vertexAttribPointer(0, 2, FLOAT, false, 0, 0)
drawArrays(TRIANGLES, 0, 6)
The buffer that is being used there (Buffer 5) is setup as follows:
bufferData(ARRAY_BUFFER, [-1,-1,1,-1,-1,1,-1,1,1,-1,1,1], STATIC_DRAW)
And the program (Program 2) data is:
LINK_STATUS true
VALIDATE_STATUS false
DELETE_STATUS false
ACTIVE_UNIFORMS 0
ACTIVE_ATTRIBUTES 1
Vertex shader:
#ifdef GL_ES
precision highp float;
#endif
attribute vec2 aPosition;
void main(void) {
gl_Position = vec4(aPosition, 0, 1);
}
Fragment shader:
#ifdef GL_ES
precision highp float;
#endif
void main(void) {
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
Other state I think could be relevant:
CULL_FACE false
CULL_FACE_MODE BACK
FRONT_FACE CCW
BLEND false
DEPTH_TEST false
VIEWPORT 0, 0 640 x 480
SCISSOR_TEST false
SCISSOR_BOX 0, 0 640 x 480
COLOR_WRITEMASK true,true,true,true
DEPTH_WRITEMASK true
STENCIL_WRITEMASK 0xffffffff
FRAMEBUFFER_BINDING null
What I expected to see from that setup/commands is a red quad taking up the whole clip space, but what I see is simply the cleared screen, as the drawArrays doesn't seem to be doing anything. Can anybody spot what I'm missing? Any tips on how to debug this would be very welcome too!
Here:
bufferData(ARRAY_BUFFER, [-1,-1,1,-1,-1,1,-1,1,1,-1,1,1], STATIC_DRAW)
replace to:
bufferData(ARRAY_BUFFER, new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]), STATIC_DRAW)
Because webgl doesn't know which type you are passing here (integer or float or byte). Example:
http: jsfiddle.net/9QxAz/
After reading #user1724911's fiddle, I found out what I missed is enabling the vertex attribute array - stupidly simple mistake. I'm actually surprised I didn't get any warning from webgl inspector about this, but the solution was simply to add a call to enable that attribute:
gl.enableVertexAttribArray(program.attributes.aPosition);
I am trying to get the filter type set in the sampler stat in the Shader code. I am not getting a way to retrieve that. Can someone suggest me a way to do that??
Texture2D InputTexture;
SamplerState Sampler;
float4 PSMain(float2 pos: TEXCOORD, float4 SVP : SV_POSITION) : SV_TARGET {
float4 image = InputTexture.Sample(Sampler, pos);
//How to get Filter type - Sampler.Filter???
return image;
}
Doesn't work the above option for me. Can someone help me out?
Thanks.
You can't do that, the way to go if you want altering behaviour in your shader is to use either shader constants and branch based on them, or different versions of your shader.
I am trying to do a progressive rendering using the previous rendering as a texture to the next one.
EDIT 1: As suggested in the comments, I did updated my version of THREE.js to the latest available, and kept my old code, the result is the same (even if the vertical positions of objects flipped). And my problem still remains. Please do consider my update and my pray for help.
Original message:
My fragment shader should only increment the color on the green channel with 0.1, like this:
#ifdef GL_ES
precision highp float;
#endif
uniform sampler2D sampa;
varying vec2 tc;
void main(void)
{
vec4 c = texture2D(sampa, tc);
vec4 t = vec4(c.x, c.y + .1, c.z, 1.);
gl_FragColor = t;
}
My composer is like this:
composer.addPass(renderModel);
composer.addPass(screenPass);
composer.addPass(feedPass);
Where renderModel is a RenderPass, rendering my scene in which I have a plane and a cube.
and screenPass and feedPass are identical with the only difference being that one renders on screen the other one renders in writeBuffer (composer.renderTarget1).
var renderModel = new THREE.RenderPass(scene, camera);
renderModel.clear = false;
screenPass = new THREE.ShaderPass(shader2, 'sampa');
screenPass.renderToScreen = true;
screenPass.clear = false;
screenPass.needsSwap = false;
feedPass = new THREE.ShaderPass(shader2, 'sampa');
feedPass.renderToScreen = false;
feedPass.clear = false;
feedPass.needsSwap = false;
And in the animation loop, I have something like this:
composer.render();
if(step % 250 == 0)
{
newmat = new THREE.MeshBasicMaterial(
{
map : composer.renderTarget1
});
plane.material = newmat;
}
step++;
requestAnimationFrame(animate);
The part with step % 250 is to delay the change of material.
Anyway, the problem is that the plane is disappearing when that happens. Even if it is correctly rendered in the first 250 steps. I guess it is still there but with no texture data, so it is not actually rendered.
I know that EffectComposer is not part of the library, and it is found only in examples, and might not be supported, but I would really do with any advice on this situation, and any answer will be greatly appreciated.
As for any other info about the problem, or some other code that might help I very am willing to share.
Could you point out what am I doing wrong?
I thank you for your kindness.
It seems the solution to this problem is to use two RenderTargets, and switch between them on every step. My limited knowledge stops me from understanding exactly why but this is exactly how EffectComposer work.
For those who might have this problem and need a solution you should try to set needsSwap to true for your shaders pass.
And if you do not use EffectComposer, then remember to use two rendertargets.
I need my sprite to transition to one color to another and on and on... like blue tint then green then purple, but i cannot find any good actions for that and am wondering, should i use animations? or is there an incorporated action for this?
you can use CCTintTo action to change the color of the sprite
[sprite runAction:[CCTintTo actionWithDuration:2 red:255 green:0 blue:0]];
since i saw several questions about replacing pixel colours in sprites, and i did'nt see any good solution (all solution only tint the color, and none of them is able to change an array of colours without forcing you into creating multiple image layers which construct the final image you want, i.e: one layer for pans, other for show, other for shirt, another for hair colour... and it goes on - note that they do have their advantages like the ability to use accurate gradients)
my solution allows you to change array of colors, meaning you can have a single image with a known colors (you dont want any gradiants in this layer, only colours that you KNOW their values - PS this only applies to colors you intent to change, other pixels can have any colour you want)
if you need gradiants over the colours you change, create an additional image with only the shading and place it as a child of the sprite.
also be aware that i am super-new to cocos2d/x (3 days), and that this code is written for cocos2dx but can be ported to cocos2d easily.
also note that i didnt test it on android only on iOS, i am not sure how capable is android official gcc and how will it deal with the way i allocate _srcC and _dstC, but again, this is easily portable.
so here it goes:
cocos2d::CCSprite * spriteWithReplacedColors( const char * imgfilename, cocos2d::ccColor3B * srcColors, cocos2d::ccColor3B * dstColors, int numColors )
{
CCSprite *theSprite = NULL;
CCImage *theImage = new CCImage;
if( theImage->initWithImageFile( imgfilename ) )
{
//make a color array which is easier to work with
unsigned long _srcC [ numColors ];
unsigned long _dstC [ numColors ];
for( int c=0; c<numColors; c++ )
{
_srcC[c] = (srcColors[c].r << 0) | (srcColors[c].g << 8) | (srcColors[0].b << 16);
_dstC[c] = (dstColors[c].r << 0) | (dstColors[c].g << 8) | (dstColors[0].b << 16);
}
unsigned char * rawData = theImage->getData();
int width = theImage->getWidth();
int height = theImage->getHeight();
//replace the colors need replacing
unsigned int * b = (unsigned int *) rawData;
for( int pixel=0; pixel<width*height; pixel++ )
{
register unsigned int p = *b;
for( int c=0; c<numColors; c++ )
{
if( (p&0x00FFFFFF) == _srcC[c] )
{
*b = (p&0xFF000000) | _dstC[c];
break;
}
}
b++;
}
CCTexture2D *theTexture = new CCTexture2D();
if( theTexture->initWithData(rawData, kCCTexture2DPixelFormat_RGBA8888, width, height, CCSizeMake(width, height)) )
{
theSprite = CCSprite::spriteWithTexture(theTexture);
}
theTexture->release();
}
theImage->release();
return theSprite;
}
to use it just do the following:
ccColor3B src[] = { ccc3( 255,255,255 ), ccc3( 0, 0, 255 ) };
ccColor3B dst[] = { ccc3( 77,255,77 ), ccc3( 255, 0 0 ) };
//will change all whites to greens, and all blues to reds.
CCSprite * pSprite = spriteWithReplacedColors( "character_template.png", src, dst, sizeof(src)/sizeof(src[0]) );
of course if you need speed, you would create an extension for a sprite that create a pixel shader that does it hw accelerated at render time ;)
btw: this solution might cause some artefacts on the edges on some cases, so you can create a large image and scale it down, letting GL minimise the artefact.
you can also create "fix" layers with black outlines to hide the artefacts and place it on top etc.
also make sure you don't use these 'key' colors on the rest of the image you don't want the pixels changed.
also keep in mind that the fact that the alpha channel is not changed, and that if you use basic images with pure red/green/blue colors only, you can also optimize this function to eliminate all artefacts on edges automatically (and avoid in many cases, the need for an additional shade layer) and other cool stuff (multiplexing several images into a single bitmap - remember palette animation?)
enjoy ;)
In case someone wanted this for cocos2d-x here is the code:
somesprite->runAction(TintTo::create(float duration, Color3b &color));