# Apply gradient shader to a torus

**URL:** <https://discourse.processing.org/t/apply-gradient-shader-to-a-torus/40491>\
**Category:** Coding Questions\
**Created:** [January 6, 2023, 9:55pm UTC](https://discourse.processing.org/t/apply-gradient-shader-to-a-torus/40491 "2023-01-06T21:55:45Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tilman](https://avatars.discourse-cdn.com/v4/letter/t/90db22/32.png) [@Tilman](https://discourse.processing.org/u/Tilman)\
**Post date:** [January 6, 2023, 9:55pm UTC](https://discourse.processing.org/t/apply-gradient-shader-to-a-torus/40491/1 "2023-01-06T21:55:45Z")

</div>

Hi!  
I would like to color a torus red on the left half and blue on the right half surely with a transition.  
Best check my next post below as I made a mockup of what I want to accomplish.

↓↓↓

---

<div class="post-metadata">

**Author:** ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)\
**Post date:** [January 8, 2023, 8:40am UTC](https://discourse.processing.org/t/apply-gradient-shader-to-a-torus/40491/2 "2023-01-08T08:40:49Z")

</div>

The following may not be exactly what you had in mind but it does run in the p5.js WebEditor. The errors came from the shader.vert file, so I used new files from here: [https://github.com/aferriss/p5jsShaderExamples/tree/gh-pages/6\_3d/6-1\_rectangle](https://github.com/aferriss/p5jsShaderExamples/tree/gh-pages/6_3d/6-1_rectangle) and they allowed it to run without error.

```auto
let redGreen;

function preload() {
  redGreen = loadShader("shader.vert", "shader.frag");
}

function setup() {
  createCanvas(800, 600, WEBGL);
  noStroke();
}

function draw() {
  background(0);
  shader(redGreen);
  rotateX(frameCount * 0.01);
  rotateY(frameCount * 0.01);
  rotateZ(PI/2);
  torus(180, 40, 100, 12);
}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
}

```

shader.frag

```auto
precision mediump float;

varying vec2 vTexCoord;

void main() {
  // draw the texcoords to the screen
  gl_FragColor = vec4(vTexCoord.x, vTexCoord.y, 0.0 ,1.0);
}

```

shader.vert

```auto
// Get the position attribute of the geometry
attribute vec3 aPosition;

// Get the texture coordinate attribute from the geometry
attribute vec2 aTexCoord;

// When we use 3d geometry, we need to also use some builtin variables that p5 provides
// Most 3d engines will provide these variables for you. They are 4x4 matrices that define
// the camera position / rotation, and the geometry position / rotation / scale
// There are actually 3 matrices, but two of them have already been combined into a single one
// This pre combination is an optimization trick so that the vertex shader doesn't have to do as much work

// uProjectionMatrix is used to convert the 3d world coordinates into screen coordinates
uniform mat4 uProjectionMatrix;

// uModelViewMatrix is a combination of the model matrix and the view matrix
// The model matrix defines the object position / rotation / scale
// Multiplying uModelMatrix * vec4(aPosition, 1.0) would move the object into it's world position

// The view matrix defines attributes about the camera, such as focal length and camera position
// Multiplying uModelViewMatrix * vec4(aPosition, 1.0) would move the object into its world position in front of the camera
uniform mat4 uModelViewMatrix;

varying vec2 vTexCoord;

void main() {

  // copy the position data into a vec4, using 1.0 as the w component
  vec4 positionVec4 = vec4(aPosition, 1.0);

  // Move our vertex positions into screen space
  // The order of multiplication is always projection * view * model * position
  // In this case model and view have been combined so we just do projection * modelView * position
  gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;

  // Send the texture coordinates to the fragment shader
  vTexCoord = aTexCoord;
}

```

---

<div class="post-metadata">

**Author:** ![Tilman](https://avatars.discourse-cdn.com/v4/letter/t/90db22/32.png) [@Tilman](https://discourse.processing.org/u/Tilman)\
**Post date:** [January 8, 2023, 9:18pm UTC](https://discourse.processing.org/t/apply-gradient-shader-to-a-torus/40491/3 "2023-01-08T21:18:10Z")

</div>

@svan thank you!!  
It seems I copy pasted something wrong. Yes, I had the shader from that gitthub page loaded too. The problem I still have is that with the torus the gradient transition has a sharp break at one side like if the torus had a start and a end position:  
How it looks:  
 ![Bildschirmfoto 2023-01-08 um 22.11.12](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/9/7/979d2b0bffd1c0717b395e67ea9c418b740636ce.png)

I am looking for a result like this from red to blue. I mocked it up in photoshop that is why the transition of the gradient looks not so smooth:  
 ![Bildschirmfoto 2023-01-08 um 21.44.18](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/5/b/5bfa195244fa1f375246e83021a5d35b4766b9d2.png)

Just for reference the code:

**sketch:**

```auto
let redGreen;

function preload() {
  redGreen = loadShader("shader.vert", "shader.frag");
}

function setup() {
  createCanvas(400, 400, WEBGL);
  noStroke();
}

function draw() {
  background(0);
  shader(redGreen);
  //rotateX(frameCount * 0.01);
  //rotateY(frameCount * 0.01);
  //rotateZ(PI/2);
  translate(200-width/2,200-height/2);
  torus(50, 20, 100, 12);
  
}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
}

```

**shader.vert**

```auto

attribute vec3 aPosition;

attribute vec2 aTexCoord;

uniform mat4 uProjectionMatrix;

uniform mat4 uModelViewMatrix;

varying vec2 vTexCoord;

void main() {

  vec4 positionVec4 = vec4(aPosition, 1.0);

  gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;

  vTexCoord = aTexCoord;
}

```

**shader.frag**

```auto
precision mediump float;

varying vec2 vTexCoord;

void main() {
  // draw the texcoords to the screen
  gl_FragColor = vec4(vTexCoord.x, vTexCoord.y, 0.0 ,1.0);
}

```

---

<div class="post-metadata">

**Author:** ![Tilman](https://avatars.discourse-cdn.com/v4/letter/t/90db22/32.png) [@Tilman](https://discourse.processing.org/u/Tilman)\
**Post date:** [January 9, 2023, 9:19am UTC](https://discourse.processing.org/t/apply-gradient-shader-to-a-torus/40491/4 "2023-01-09T09:19:12Z")

</div>

help would be very much appreciated. Also for more online resources I could read up on. Thanks!

---

<div class="post-metadata">

**Author:** ![Tilman](https://avatars.discourse-cdn.com/v4/letter/t/90db22/32.png) [@Tilman](https://discourse.processing.org/u/Tilman)\
**Post date:** [January 10, 2023, 9:47pm UTC](https://discourse.processing.org/t/apply-gradient-shader-to-a-torus/40491/5 "2023-01-10T21:47:39Z")

</div>

Anyone can help here? 🙂

---

<div class="post-metadata">

**Author:** ![sableraph](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/sableraph/32/251_2.png) [@sableraph](https://discourse.processing.org/u/sableraph)\
**Post date:** [January 11, 2023, 1:53pm UTC](https://discourse.processing.org/t/apply-gradient-shader-to-a-torus/40491/6 "2023-01-11T13:53:01Z")

</div>

Since this seems like a shader question and not everyone is familiar with glsl around here, I’d recommend asking on the [shader zone](https://discord.gg/GNKVmwpScX) discord server. Hope this helps

---

<div class="post-metadata">

**Author:** ![scudly](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/scudly/32/5597_2.png) [@scudly](https://discourse.processing.org/u/scudly)\
**Post date:** [January 11, 2023, 5:02pm UTC](https://discourse.processing.org/t/apply-gradient-shader-to-a-torus/40491/7 "2023-01-11T17:02:49Z")

</div>

Instead of passing a uv pair for the texture coordinates, you only need a single float value based on the vertex y-coordinate. In your fragment shader, just have

```auto
varying float high;

void main() {
  gl_Fragcolor = vec4( high, 0., 1.-high, 1. );
}

```

Then in your vertex shader, you have to compute `high` from your `aPosition.y`. Scale and offset it so it ranges from `0` to `1`.

---

<div class="post-metadata">

**Author:** ![scudly](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/scudly/32/5597_2.png) [@scudly](https://discourse.processing.org/u/scudly)\
**Post date:** [January 11, 2023, 5:37pm UTC](https://discourse.processing.org/t/apply-gradient-shader-to-a-torus/40491/8 "2023-01-11T17:37:35Z")

</div>

I played around with this a bit. It looks like p5 defines the torus model coordinates to scale from -1 to 1 from the middle of the big ring with the smaller ring extending from there. So if you had a `torus( 100, 20 )` as an example, in your vertex shader, your `aPosition.y` would range from `-1.2` to `1.2`. For that case, I would have `high = aPosition.y / 2.4 + 0.5;` in the vertex shader.

---

<div class="post-metadata">

**Author:** ![Tilman](https://avatars.discourse-cdn.com/v4/letter/t/90db22/32.png) [@Tilman](https://discourse.processing.org/u/Tilman)\
**Post date:** [January 11, 2023, 6:01pm UTC](https://discourse.processing.org/t/apply-gradient-shader-to-a-torus/40491/9 "2023-01-11T18:01:22Z")

</div>

> [@scudly](#):
>
> high = aPosition.y / 2.4 + 0.5

thank you @scudly for playing around with this. yes there is something about how p5 calculates the torus that is not ideal for shaders it seems. But boy do I know nothing about shaders and 3d 🙂

I will try to test your ideas although I don´t know exactly know where to put the lines of your code. I will try to read the shader introduction again and hope it helps to understand your suggestions better. Thanks!

---

<div class="post-metadata">

**Author:** ![scudly](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/scudly/32/5597_2.png) [@scudly](https://discourse.processing.org/u/scudly)\
**Post date:** [January 11, 2023, 6:14pm UTC](https://discourse.processing.org/t/apply-gradient-shader-to-a-torus/40491/10 "2023-01-11T18:14:37Z")

</div>

My vertex shader is

```auto
uniform mat4 uProjectionMatrix;
uniform mat4 uModelViewMatrix;
attribute vec3 aPosition;
varying float high;

void main() {
  high = aPosition.y / 2.4 + 0.5;
  gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aPosition, 1.0);
}

```

where the 2.4 number depends on the scaling of torus you create. Specifically, the ratio of the two radii.

---

<div class="post-metadata">

**Author:** ![Tilman](https://avatars.discourse-cdn.com/v4/letter/t/90db22/32.png) [@Tilman](https://discourse.processing.org/u/Tilman)\
**Post date:** [January 11, 2023, 7:25pm UTC](https://discourse.processing.org/t/apply-gradient-shader-to-a-torus/40491/11 "2023-01-11T19:25:21Z")

</div>

Thanks, when I paste the above in the vertex shader and the following int o the shader.frag:

```auto
precision mediump float;

varying float high;

void main() {
  gl_Fragcolor = vec4( high, 0., 1.-high, 1. );
}

```

I get this error:  
🌸 p5.js says: [sketch.js, line 19] An error with message “Failed to execute ‘useProgram’ on ‘WebGLRenderingContext’: parameter 1 is not of type ‘WebGLProgram’.” occurred inside the p5js library when torus was called. If not stated otherwise, it might be an issue with the arguments passed to torus. ([Reference](http://p5js.org/reference/#/p5/torus))

​Do I need to change somethin in the stech file too?

## Preview

---

<div class="post-metadata">

**Author:** ![scudly](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/scudly/32/5597_2.png) [@scudly](https://discourse.processing.org/u/scudly)\
**Post date:** [January 11, 2023, 8:29pm UTC](https://discourse.processing.org/t/apply-gradient-shader-to-a-torus/40491/12 "2023-01-11T20:29:51Z")

</div>

Here’s my full code which runs without errors on my linux chrome:

```auto
let redGreen;

function setup() {
  createCanvas(400, 400, WEBGL);
  redGreen = createShader( vs, fs );
  noStroke();
}

function draw() {
  background(0);
  shader(redGreen);
  torus( 100, 20, 100, 12);
}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
}

let vs = `
uniform mat4 uProjectionMatrix;
uniform mat4 uModelViewMatrix;
attribute vec3 aPosition;
varying float high;

void main() {
  vec4 positionVec4 = vec4(aPosition, 1.0);
  gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;
  high = aPosition.y / 2.4 + 0.5;
}
`;

let fs = `
precision mediump float;
varying float high;

void main() {
  gl_FragColor = vec4( high, 0., 1.-high, 1.0 );
}
`;

```

---

<div class="post-metadata">

**Author:** ![Tilman](https://avatars.discourse-cdn.com/v4/letter/t/90db22/32.png) [@Tilman](https://discourse.processing.org/u/Tilman)\
**Post date:** [January 11, 2023, 8:45pm UTC](https://discourse.processing.org/t/apply-gradient-shader-to-a-torus/40491/13 "2023-01-11T20:45:35Z")

</div>

running here too! That´s awesome. Thank you! Will dig into this now and try to understand. The result is spot on!
