# 1. Draw a rectangle

Last article learned how to draw a line, now learn how to draw a surface. Start with drawing a rectangle. In fact, the idea of drawing a rectangle is the same as that of drawing a line, except that the area restricted by drawing a line is narrower and the area restricted by drawing a rectangle is wider. Let's start with the code for drawing the first rectangle.

## 1.1 Draw using if statement

As you've said before in mind, this is just a practice. We encapsulate a function, box0, that draws a rectangle. The process is to define the values of the four boundaries. If the coordinates of the rectangular area are satisfied, it returns 1.0, otherwise it returns 0.0.

```float box0(vec2 st){
float left = 0.0;
float right = 0.4;
float top = 0.6;
float bottom = 0.2;
if(st.x > left && st.x < right && st.y > bottom && st.y < top){
return 1.0;
}else{
return 0.0;
}
}
```

Call Procedure

```pct = box0(st);
color = mix(color,line_color,pct);
```

The result is as follows, drawing a yellow rectangle based on the four boundaries defined ## 1.2 Drawing with step function

Drawing with the step function is actually the first way to use the step function conversion. By the way, avoid using the if judgment in writing the shader as much as possible, because it takes a lot of performance to make the if judgment in the piecewise processing, this time encapsulated as the function box1

```float box1(vec2 st){

float left = 0.0;
float right = 0.4;
float top = 0.6;
float bottom = 0.2;

//Left and right boundary
float x1 = step(left,st.x);
float x2 = step(right,1.0-st.x); //The detection value should be less than the right boundary before returning 1.0, so use 1.0-st.x

//Upper and lower boundaries
float y1 = step(bottom,st.y);
float y2 = step(top,1.0-st.y);//Detection values less than the upper boundary should return 1.0, so use 1.0-st.y

float pct = x1 * x2 *y1 *y2;
return pct;
}
```

There are no more calls, just replace the function name, and the result is as follows ## 1.3 Drawing using the step function simplification method

The above functions are processed separately using screen coordinates st.x and st.y. Can they be merged or not? The answer is yes, but first the lower left boundary is processed, then the upper right boundary is processed, and then they are merged by multiplication, as follows:

```float box2(vec2 st){

float left = 0.0;
float right = 0.4;
float top = 0.6;
float bottom = 0.2;

//Lower Left Boundary
vec2 bl = step(vec2(left,bottom),st);
float pct = bl.x * bl.y;

//Upper Right Boundary
vec2 tr = step(vec2(right,top),1.0-st);//The detection value should be less than the upper right boundary before returning 1.0, so use 1.0-st
pct *= tr.x * tr.y;

return pct;
}
```

results of enforcement ## 1.4 Drawing with abs symmetry

In fact, the method of drawing rectangle can be further simplified. Using the idea of symmetry through the origin with abs function, the rectangle can be drawn simply by restricting the upper and right boundaries, as follows:

```float box3(vec2 st){

float right = 0.9;
float top = 0.3;

//Draw a symmetrical quadrilateral with an origin in the upper right corner
vec2 bl = 1.0-step(vec2(right,top),abs(st));
float pct = bl.x * bl.y;

return pct;
}
```

give the result as follows ## 1.5 Draw rectangular border

The fourth method is the smallest and taller code, on which we can deduct a smaller rectangle and get a rectangular border as follows

```float box4(vec2 st){

float right = 0.9;
float top = 0.3;
float line_width = 0.03;

//Draw a symmetrical quadrilateral with an origin in the upper right corner
vec2 b1 = 1.0-step(vec2(right,top),abs(st));

float boxouter = b1.x * b1.y;

vec2 b2 = 1.0-step(vec2(right-line_width,top-line_width),abs(st));
float boxinner = b2.x * b2.y;

float pct = boxouter -boxinner;

return pct;
}
```

The results are as follows If you are not satisfied with the result of drawing, you can adjust the width of the border and wireframe. Some friends may ask you what to do if I don't want it to go through the origin, but want to draw in this way. You can draw it first and then pan it. Panning is not mentioned here. Write an article later that will focus on panning, rotating, zooming of the graphic.

# 2. Draw a circle

## 2.1 Draw a circle

The idea of drawing a circle is the same. The circle is defined as a set of points whose distance from a point is equal to a fixed length. We use distance(), length() or sqrt() to draw a circle, this time using the smoothstep function, in order to eliminate aliasing, as follows

```float circle(vec2 st,vec2 center,float radius) {
float blur = 0.002;

//float pct = distance(st,center);// Calculate the distance from any point to the center of a circle

vec2 tC = st-center; //Compute the vector from the center of a circle to any point
//float pct = length(tC); // Finding Length Using the Length Function
float pct = sqrt(tC.x*tC.x+tC.y*tC.y);//Find Length by Squaring

}
```

give the result as follows ## 2.2 Draw a circular box

Draw a circle, drawing a circle box is to drop a smaller circle on the circle, as follows

```float circleLine(vec2 st,vec2 center,float radius) {
float pct = distance(st,center);//Calculate the distance from any point to the center of a circle
float line_width = 0.02;
float blur = 0.002;
}
```

give the result as follows # 3. demo code

Old rule, demo all code attached

```<body>
<div id="container"></div>
<script src="http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.js"></script>
<script>
var container;
var camera, scene, renderer;
var uniforms;
void main() {
gl_Position = vec4( position, 1.0 );
}
`
#ifdef GL_ES
precision mediump float;
#endif
uniform float u_time;
uniform vec2 u_mouse;
uniform vec2 u_resolution;

float box0(vec2 st){
float left = 0.0;
float right = 0.4;
float top = 0.6;
float bottom = 0.2;
if(st.x > left && st.x < right && st.y > bottom && st.y < top){
return 1.0;
}else{
return 0.0;
}
}

float box1(vec2 st){

float left = 0.0;
float right = 0.4;
float top = 0.6;
float bottom = 0.2;

//Left and right boundary
float x1 = step(left,st.x);
float x2 = step(right,1.0-st.x); //The detection value should be less than the right boundary before returning 1.0, so use 1.0-st.x

//Upper and lower boundaries
float y1 = step(bottom,st.y);
float y2 = step(top,1.0-st.y);//Detection values less than the upper boundary should return 1.0, so use 1.0-st.y

float pct = x1 * x2 *y1 *y2;
return pct;
}

float box2(vec2 st){

float left = 0.0;
float right = 0.4;
float top = 0.6;
float bottom = 0.2;

//Lower Left Boundary
vec2 bl = step(vec2(left,bottom),st);
float pct = bl.x * bl.y;

//Upper Right Boundary
vec2 tr = step(vec2(right,top),1.0-st);//The detection value should be less than the upper right boundary before returning 1.0, so use 1.0-st
pct *= tr.x * tr.y;

return pct;
}

float box3(vec2 st){

float right = 0.9;
float top = 0.3;

//Draw a symmetrical quadrilateral with an origin in the upper right corner
vec2 bl = 1.0-step(vec2(right,top),abs(st));
float pct = bl.x * bl.y;

return pct;
}

float box4(vec2 st){

float right = 0.9;
float top = 0.3;
float line_width = 0.03;

//Draw a symmetrical quadrilateral with an origin in the upper right corner
vec2 b1 = 1.0-step(vec2(right,top),abs(st));

float boxouter = b1.x * b1.y;

vec2 b2 = 1.0-step(vec2(right-line_width,top-line_width),abs(st));
float boxinner = b2.x * b2.y;

float pct = boxouter -boxinner;

return pct;
}

float circle(vec2 st,vec2 center,float radius) {
float blur = 0.002;

//float pct = distance(st,center);// Calculate the distance from any point to the center of a circle

vec2 tC = st-center; //Compute the vector from the center of a circle to any point
//float pct = length(tC); // Finding Length Using the Length Function
float pct = sqrt(tC.x*tC.x+tC.y*tC.y);//Find Length by Squaring

}

float circleLine(vec2 st,vec2 center,float radius) {
float pct = distance(st,center);//Calculate the distance from any point to the center of a circle
float line_width = 0.02;
float blur = 0.002;
}

void main( void ) {

//Window coordinates adjusted to [-1,1], coordinate origin at the center of the screen
vec2 st = (gl_FragCoord.xy * 2. - u_resolution) / u_resolution.y;

//Window coordinates adjusted to [0,1], coordinate origin in lower left corner of screen
//vec2 st = gl_FragCoord.xy/u_resolution;

vec3 line_color = vec3(1.0,1.0,0.0);
vec3 color = vec3(0.6);//background color
float pct = 0.0;

pct = box0(st);
pct = box1(st);
pct = box2(st);
pct = box3(st);
pct = box4(st);
//color = mix(color,line_color,pct);

pct = circle(st,vec2(-0.3),0.4);
//color = mix(color,line_color,pct);

pct = circleLine(st,vec2(0.3),0.4);
color = mix(color,line_color,pct);

gl_FragColor = vec4(color, 1);
}
`

init();
animate();

function init() {
container = document.getElementById('container');

camera = new THREE.Camera();
camera.position.z = 1;

scene = new THREE.Scene();

var geometry = new THREE.PlaneBufferGeometry(2, 2);

uniforms = {
u_time: {
type: "f",
value: 1.0
},
u_resolution: {
type: "v2",
value: new THREE.Vector2()
},
u_mouse: {
type: "v2",
value: new THREE.Vector2()
}
};

uniforms: uniforms,
});

var mesh = new THREE.Mesh(geometry, material);

renderer = new THREE.WebGLRenderer();
//renderer.setPixelRatio(window.devicePixelRatio);

container.appendChild(renderer.domElement);

onWindowResize();

document.onmousemove = function (e) {
uniforms.u_mouse.value.x = e.pageX
uniforms.u_mouse.value.y = e.pageY
}
}

function onWindowResize(event) {
renderer.setSize(800, 800);
uniforms.u_resolution.value.x = renderer.domElement.width;
uniforms.u_resolution.value.y = renderer.domElement.height;
}

function animate() {
requestAnimationFrame(animate);
render();
}

function render() {
uniforms.u_time.value += 0.02;
renderer.render(scene, camera);
}
</script>
</body>
```