Hot answers tagged

84

It's probably easiest to understand by contrast with raytracing. To render a primitive with raytracing, you need a function that, given the primitive and input ray, tells you exactly where that ray hits the primitive. Then you can test the ray against all relevant primitives, and pick the closest intersection. This means potentially a lot of non-local data ...


43

What causes branching in GLSL depends on the GPU model and OpenGL driver version. Most GPUs seem to have a form of "select one of two values" operation that has no branching cost: n = (a==b) ? x : y; and sometimes even things like: if(a==b) { n = x; m = y; } else { n = y; m = x; } will be reduced to a few select-value operation with no ...


36

I think I get what you're trying to ask. I assume your primary concern are the non-uniform variables defined outside of main(): float left; float right; float mscaled; float xn; float xm; Let's take a look at how the GPU and GLSL work. The GPU does not have a stack or a call activation records. There is not a way to simulate scope or local variablaes in ...


35

specular lighting of directional light more area has specular lighting when camera is far from an object Yep, looks right to me. The specular area for directional lights is supposed to be more or less constant w.r.t. the camera, given the same reflection surface. To compare, we can look at the phenomenon known as sunglint, which is basically specular ...


33

First of all, for every 3D vertex there is infinite tangent and bi-tangent vectors. The below image explains why there is an infinite number of tangent spaces for each vertex, the tangent and bitangent can have any direction in the shown plane. So inorder to properly calculate the most useful1 tangent space, we want our tangent space to be aligned such that ...


31

While this answer does not tell what is wrong with your approach, it presents a simpler way to render skyboxes. Traditional way (textured cube) A straightforward way for creating skyboxes is to render a textured cube centered to the camera position. Each face of the cube consists of two triangles and a 2D texture (or part of an atlas). Due to texture ...


28

These functions will perform very badly. I suggest using functions that are written with the GPU in mind. Here are mine: vec3 rgb2hsv(vec3 c) { vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); float d = q.x - ...


19

First, it helps to know that GPUs always evaluate fragment/pixel shaders on 2x2 blocks of pixels at a time. (Even if only some of those pixels ultimately need to be drawn, while others are outside the polygon or occluded - the unneeded fragments are masked out instead of being written at the end). The screenspace derivative of a variable (or expression) v ...


15

How do objects show color? Well, an 100% red object looks red because it absorbs all other wavelengths of light (orange,yellow,green..you know, a rainbow) and reflects only red. So what if you shone pure blue light on a pure red surface? Well it would absorb the blue light and reflect.. nothing. Hence black. I'm sorry for the terrible picture


15

At first you should pre-compute as much data as you can and avoid computing the same values for every pixel. You have such a fragment: transpose(inverse(mat3(modelMatrix)) This inverts the matrix, which is not so trivial operation and despite the fact that input data are the same for each pixel (so the results will be the same) it's recomputing this for ...


13

Your lighting equation is physically correct. However, in real life, one almost never sees highly pure colors. (An exception is when lasers are involved.) That's probably why your intuition is that red * blue = violet - a more realistic red might be something like (1, 0.1, 0.1), and a blue (0.1, 0.1, 1). Multiply those and you get (0.1, 0.01, 0.1), which ...


13

I didn't have any tiles handy that looked good with distortion, so here's a version of the effect I mocked up with these Kenney tiles instead: I'm using a flowmap like this, where red = rightward flow and green = upward, yellow being both. Each pixel corresponds to one tile, with the bottom-left pixel being the tile at (0, 0) in my world coordinate system. ...


13

I've been redirected here after posting this on twitter : https://twitter.com/Gaxil/status/1268165270541078529 I can give you some details of my implementation, even if I know that it's a quite different approach of the original one. So, in the vertex shader, I access a compute buffer in read/write mode. That allows me to store the world position of the ...


12

I tried to implement what teodron suggested: void main() { vec2 uv = gl_FragCoord.xy / resolution.xy; float sepoffset = 0.005*cos(iGlobalTime*3.0); if (uv.y > 0.3 + sepoffset)// is air - no reflection or effect { gl_FragColor = texture2D(texture, vec2(uv.x, -uv.y)); } else { // Compute the mirror effect. ...


12

No, but OpenGL might ;) The base Vulkan specification only supports SPIR-V. However, Vulkan does allow for vendor extensions. And NVIDIA is already on-record on this matter; they will be providing a Vulkan extension to be able to shove GLSL into their Vulkan implementation. That shouldn't be taken to mean everyone else will. However, let's not forget that ...


11

It's not particularly useful for you but you should definitely leave it at 1. It's used when applying transformations to the model. Matrix multiplication can only multiply numbers, it can't add. That makes moving objects impossible unless the 4th component exists. Let's look at an example: If we want to move the vector $$\vec v = \begin{bmatrix}a \\ b\\c\...


10

The performance cost of branching can be not trivially small too. In your case all vertices and fragments being drawn will be taking the same path through your shaders, so on modern desktop hardware it would not be as bad as it could be, but you're using ES2 which implies that you're not using modern desktop hardware. The worst case with branching will go ...


10

Khronos provides a reference GLSL compiler. It is capable of validating GLSL up to version 3.50 (full support) and up to 4.50 (partial support). It also handles ESSL (OpenGL ES's GLSL). The tool verifies that the shader conforms to the GLSL specification. This does not necessarily guarantee that it works with all drivers but it does guarantee that the ...


10

What you're looking for is instancing. You simply call glDrawArraysInstanced​ or glDrawElementsInstanced​, passing the number of instances that you want. There are two ways to then determine per-instance data: The gl_InstanceID vertex shader input tells you which instance is currently being processed. Your vertex shader can have an internal mechanism for ...


10

Well, when asked to design any shader, we should start by breaking things down to smaller problems. And just as note the glittering effect doesn't actually makes the shader looks good, but the overall lighting and effect, using only one of them won't look as good. First of all let us state what is not directly part of the shader: The shadowing is not ...


10

Yes, it isn't what we want to do. Matrix multiplication is not communative, which is to say that switching the order produces different things. Think of it this way, if you do these operations: Turn left 90 degrees Go forward 10 meters You end up at a different position then if you did: Go forward 10 meters Turn left 90 degrees This doesn't mean it's ...


10

This is not technically an answer to your question, but is a better work around in my opinion. You can pass the dimensions of the boxes and the radius of the corners to the fragment shaders and round the corners that way. Basically, you take the current texture coordinates, multiply each coordinate of it by the dimensions of the window to get the ...


9

If you have the EXT_texture_filter_anisotropic extension, you can set the maximum texture anisotropy parameter using glTexParameterf to allow the driver to take more samples during texture filtering. A code snippet: float aniso = 0.0f; glBindTexture(GL_TEXTURE_2D, texName); glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &aniso); glTexParameterf(...


9

You already know what you have to do, I'll just summarize it. There are three ways to solve your problem: Go ahead and make a conditional like you're saying, either by sampling the texture or by creating a separate uniform for this purpose. As you probably know, adding branching on a shader is almost never a good idea, and much less so in the fragment ...


9

#define NAME VALUE is a macro, where all instances of NAME are replaced with VALUE by the pre-processor. The compiler handles constants. This ensures type safety.


9

gl_Position is a Homogeneous coordinates. Homogeneous coordinates are needed for perspective projection. Note, if a vector vec4(x, y, z, 1.0) is multiplied by a perspective projection matrix, this results in a Homogeneous coordinates. The projection matrix describes the mapping from 3D points of a scene, to 2D points of the viewport. The projection matrix ...


8

The trick for rapid Gaussian blurring with GLSL is to take advantage of the fact that the GPU provides linear interpolation in hardware. Therefore, you can effectively sample four 2D pixels with a single prefetch or eight 3D voxels. By deciding where to sample you can weight the output. The definitive reference is Sigg and Hadwiger's "Fast Third-Order ...


8

To answer your question let's look at how the typical OpenGL pipline works. Vertex Shader -> Geometry Shader (Optional) -> Clipping -> Rasterization -> Pixel Shader ---------------> Fragments Merge. I want to stress the fact that one pixel is not necessarily one fragment, multiple fragment can be combined to make one pixel, other fragments are discarded ...


Only top voted, non community-wiki answers of a minimum length are eligible