mirror of
https://github.com/penpot/penpot.git
synced 2025-01-21 22:22:43 -05:00
wip
This commit is contained in:
parent
e08e2bf64a
commit
6b50c17781
3 changed files with 108 additions and 43 deletions
|
@ -3,6 +3,7 @@
|
|||
(:require-macros [app.util.gl.macros :refer [slurp]])
|
||||
(:require
|
||||
["gl-matrix" :as glm]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.math :as math]
|
||||
[app.util.gl :as gl]
|
||||
[cuerdas.core :as str]
|
||||
|
@ -15,6 +16,7 @@
|
|||
|
||||
#_(def shaders (js/Map.))
|
||||
(def programs (js/Map.))
|
||||
(def program-actives (js/Map.))
|
||||
#_(def textures (js/Map.))
|
||||
#_(def framebuffers (js/Map.))
|
||||
|
||||
|
@ -53,6 +55,25 @@
|
|||
:bool 7
|
||||
:frame 8))
|
||||
|
||||
(defn get-object-border-radius-as-vec4
|
||||
"Returns a vec4 from the object border radius."
|
||||
[object]
|
||||
(let [rx (:rx object)
|
||||
ry (:ry object)
|
||||
r1 (:r1 object)
|
||||
r2 (:r2 object)
|
||||
r3 (:r3 object)
|
||||
r4 (:r4 object)]
|
||||
(cond
|
||||
(or rx ry)
|
||||
#js [(:rx object) (:ry object) (:rx object) (:ry object)]
|
||||
|
||||
(or r1 r2 r3 r4)
|
||||
#js [(:r1 object) (:r2 object) (:r3 object) (:r4 object)]
|
||||
|
||||
:else
|
||||
#js [0.0 0.0 0.0 0.0])))
|
||||
|
||||
(defn resize-canvas-to
|
||||
"Resize canvas to specific coordinates."
|
||||
[canvas width height]
|
||||
|
@ -75,28 +96,34 @@
|
|||
(defn prepare-gl
|
||||
"Prepares the WebGL context for rendering."
|
||||
[gl]
|
||||
(let [default-program (gl/create-program-from-sources gl default-vertex-shader default-fragment-shader)]
|
||||
(.set programs "default" default-program)))
|
||||
(let [default-program (gl/create-program-from-sources gl default-vertex-shader default-fragment-shader)
|
||||
default-program-actives (gl/get-program-actives gl default-program)]
|
||||
(js/console.log default-program-actives)
|
||||
(.set programs "default" default-program)
|
||||
(.set program-actives "default" default-program-actives)))
|
||||
|
||||
(defn render-gl
|
||||
"Renders the whole document to the canvas."
|
||||
[gl objects vbox]
|
||||
(let [projection (.create glm/mat3)
|
||||
projection (.projection glm/mat3 projection (:width vbox) (:height vbox))]
|
||||
projection (.projection glm/mat3 projection (:width vbox) (:height vbox))
|
||||
|
||||
(.clearColor gl 1.0 0.0 1.0 0.5)
|
||||
program (.get programs "default")
|
||||
actives (.get program-actives "default")]
|
||||
|
||||
(.clearColor gl 1.0 0.0 1.0 0.5)
|
||||
(.clear gl (.-COLOR_BUFFER_BIT gl))
|
||||
|
||||
(.viewport gl 0 0 (.-width (.-canvas gl)) (.-height (.-canvas gl)))
|
||||
|
||||
;; Enable alpha blending
|
||||
;; Enable alpha blending
|
||||
(.enable gl (.-BLEND gl))
|
||||
(.blendFunc gl (.-SRC_ALPHA gl) (.-ONE_MINUS_SRC_ALPHA gl))
|
||||
|
||||
(.useProgram gl (.get programs "default"))
|
||||
(.useProgram gl program)
|
||||
(println "---------------> vbox" (:x vbox) (:width vbox) (:y vbox) (:height vbox))
|
||||
(.uniformMatrix3fv gl (.getUniformLocation gl (.get programs "default") "u_projection") false projection)
|
||||
(.uniform4f gl (.getUniformLocation gl (.get programs "default") "u_vbox") (:x vbox) (:y vbox) (:width vbox) (:height vbox))
|
||||
(.uniformMatrix3fv gl (gl/get-program-uniform-location actives "u_projection") false projection)
|
||||
(.uniform4f gl (gl/get-program-uniform-location actives "u_vbox") (:x vbox) (:y vbox) (:width vbox) (:height vbox))
|
||||
|
||||
(doseq [[_ object] objects]
|
||||
(let [selrect (:selrect object)
|
||||
|
@ -105,25 +132,25 @@
|
|||
width (:width selrect)
|
||||
height (:height selrect)
|
||||
rotation (:rotation object)
|
||||
;; Tengo que encontrar la forma de "reordenar la matriz" para que funcione la
|
||||
;; rotación.
|
||||
;; transform (:transform object)
|
||||
;; {a :a b :b c :c d :d e :e f :f} transform
|
||||
;; matrix #_(js/Float32Array. #js [a c 0 b d 0 0 0 1])
|
||||
matrix (js/Float32Array. #js [1 0 0 0 1 0 0 0 1])
|
||||
fill (first (:fills object))]
|
||||
(js/console.log "fill" fill)
|
||||
(js/console.log "matrix" matrix)
|
||||
(.uniform1i gl (.getUniformLocation gl (.get programs "default") "u_type") (get-object-type-as-int object))
|
||||
(.uniform2f gl (.getUniformLocation gl (.get programs "default") "u_size") width height)
|
||||
(.uniform2f gl (.getUniformLocation gl (.get programs "default") "u_position") x y)
|
||||
(.uniform1f gl (.getUniformLocation gl (.get programs "default") "u_rotation") (/ (* rotation js/Math.PI) 180.0))
|
||||
#_(.uniformMatrix3fv gl (.getUniformLocation gl (.get programs "default") "u_transform") false matrix)
|
||||
border (get-object-border-radius-as-vec4 object)
|
||||
type (get-object-type-as-int object)]
|
||||
(js/console.log border)
|
||||
(.uniform4fv gl (gl/get-program-uniform-location actives "u_border") border)
|
||||
(.uniform1i gl (gl/get-program-uniform-location actives "u_type") type)
|
||||
(.uniform2f gl (gl/get-program-uniform-location actives "u_size") width height)
|
||||
(.uniform2f gl (gl/get-program-uniform-location actives "u_position") x y)
|
||||
(.uniform1f gl (gl/get-program-uniform-location actives "u_rotation") (/ (* rotation js/Math.PI) 180.0))
|
||||
#_(.uniformMatrix3fv gl (gl/get-program-uniform-location actives "u_transform") false matrix)
|
||||
;; NOTA: Esto es sólo aplicable en objetos que poseen fills (los textos no
|
||||
;; poseen fills).
|
||||
(doseq [fill (reverse (:fills object))]
|
||||
(do
|
||||
(.uniform4fv gl (.getUniformLocation gl (.get programs "default") "u_color") (parse-color (:fill-color fill) (:fill-opacity fill)))
|
||||
(.uniform4fv gl (gl/get-program-uniform-location actives "u_color") (parse-color (:fill-color fill) (:fill-opacity fill)))
|
||||
(.drawArrays gl (.-TRIANGLE_STRIP gl) 0 4)))
|
||||
|
||||
(doseq [stroke (reverse (:strokes object))]
|
||||
(do
|
||||
(.uniform4fv gl (gl/get-program-uniform-location actives "u_color") (parse-color (:stroke-color stroke) (:stroke-opacity stroke)))
|
||||
(.drawArrays gl (.-TRIANGLE_STRIP gl) 0 4)))))))
|
||||
|
||||
(mf/defc canvas
|
||||
|
|
|
@ -57,13 +57,15 @@
|
|||
[parameter get-active-name get-location-name]
|
||||
(fn [gl program]
|
||||
(let [count (.getProgramParameter gl program parameter)
|
||||
get-active (dm/get-prop gl get-active-name)
|
||||
get-location (dm/get-prop gl get-location-name)]
|
||||
(into {} (for [index (range count)]
|
||||
(let [info (get-active gl program index)
|
||||
name (.-name info)
|
||||
location (get-location gl program name)]
|
||||
[name #js {:name name :info info :location location}]))))))
|
||||
get-active (unchecked-get gl get-active-name)
|
||||
get-location (unchecked-get gl get-location-name)
|
||||
actives #js {}]
|
||||
(doseq [index (range 0 count)]
|
||||
(let [info (.apply get-active gl #js [program index])
|
||||
name (.-name info)
|
||||
location (.apply get-location gl #js [program name])]
|
||||
(.defineProperty js/Object actives name #js {:value #js {:name name :info info :location location} :enumerable true :writable false :configurable false})))
|
||||
actives)))
|
||||
|
||||
(def get-program-uniforms (get-program-active-factory (.-ACTIVE_UNIFORMS js/WebGLRenderingContext) "getActiveUniform" "getUniformLocation"))
|
||||
(def get-program-attributes (get-program-active-factory (.-ACTIVE_ATTRIBUTES js/WebGLRenderingContext) "getActiveAttrib" "getAttribLocation"))
|
||||
|
@ -75,6 +77,13 @@
|
|||
attributes (get-program-attributes gl program)]
|
||||
#js { :uniforms uniforms :attributes attributes }))
|
||||
|
||||
(defn get-program-uniform-location
|
||||
"Returns the location of the given uniform in the given program"
|
||||
[actives name]
|
||||
(let [uniforms (unchecked-get actives "uniforms")
|
||||
uniform (unchecked-get uniforms name)]
|
||||
(unchecked-get uniform "location")))
|
||||
|
||||
;;
|
||||
;; Buffers
|
||||
;;
|
||||
|
@ -90,9 +99,19 @@
|
|||
;; Framebuffers
|
||||
;;
|
||||
(defn create-framebuffer
|
||||
[gl]
|
||||
[gl attachments]
|
||||
(let [framebuffer (.createFramebuffer gl)]
|
||||
(.bindFramebuffer gl framebuffer)
|
||||
(doseq [[attachment attachment-info] attachments]
|
||||
(let [attachment-type (unchecked-get attachment-info "type")
|
||||
attachment-data (unchecked-get attachment-info "data")]
|
||||
(cond
|
||||
(= attachment-type "texture")
|
||||
(.framebufferTexture2D gl (.-FRAMEBUFFER gl) attachment (.-TEXTURE_2D gl) attachment-data 0)
|
||||
(= attachment-type "renderbuffer")
|
||||
(.framebufferRenderbuffer gl (.-FRAMEBUFFER gl) attachment (.-RENDERBUFFER gl) attachment-data)
|
||||
:else
|
||||
(throw (js/Error. (dm/str "Unknown attachment type: " attachment-type))))))
|
||||
(.bindFramebuffer gl nil)
|
||||
framebuffer))
|
||||
|
||||
|
|
|
@ -17,26 +17,45 @@ out vec4 fragColor;
|
|||
in vec2 v_texCoord;
|
||||
|
||||
uniform int u_type;
|
||||
uniform vec2 u_size;
|
||||
uniform vec4 u_color;
|
||||
uniform vec4 u_border;
|
||||
|
||||
bool isRoundedRect(in vec4 border) {
|
||||
return border.x > 0.0 || border.y > 0.0 || border.z > 0.0 || border.w > 0.0;
|
||||
}
|
||||
|
||||
// Thanks to Iñigo Quilez for this awesome functions.
|
||||
// @see https://iquilezles.org/articles/distfunctions2d/
|
||||
float sdRoundBox(in vec2 p, in vec2 b, in vec4 r) {
|
||||
r.xy = (p.x > 0.0f) ? r.xy : r.zw;
|
||||
r.x = (p.y > 0.0f) ? r.x : r.y;
|
||||
vec2 q = abs(p) - b + r.x;
|
||||
return min(max(q.x, q.y), 0.0f) + length(max(q, 0.0f)) - r.x;
|
||||
}
|
||||
|
||||
float sdCircle(in vec2 p, in float r) {
|
||||
return length(p) - r;
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Si es un rect o un frame, simplemente asignamos el color al fragColor.
|
||||
if (u_type == type_rect || u_type == type_frame) {
|
||||
fragColor = u_color;
|
||||
// Si es un circulo, comprobamos que el pixel este dentro del circulo, en caso
|
||||
// contrario descartamos el pixel.
|
||||
} else if (u_type == type_circle) {
|
||||
if (length(v_texCoord - 0.5) > 0.5) {
|
||||
discard;
|
||||
}
|
||||
if(length(v_texCoord - 0.5f) > 0.45f) {
|
||||
|
||||
fragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
} else if(length(v_texCoord - 0.5f) > 0.4f) {
|
||||
fragColor = vec4(1.0f, 0.0f, 1.0f, 1.0f);
|
||||
if (isRoundedRect(u_border)) {
|
||||
if (sdRoundBox(v_texCoord - 0.5, vec2(0.5), u_border / u_size.x) > 0.0) {
|
||||
discard;
|
||||
}
|
||||
fragColor = u_color;
|
||||
} else {
|
||||
fragColor = u_color;
|
||||
}
|
||||
// Si es un circulo, comprobamos que el pixel este dentro del circulo, en caso
|
||||
// contrario descartamos el pixel.
|
||||
} else if (u_type == type_circle) {
|
||||
if (sdCircle(v_texCoord - 0.5, 0.5) > 0.0) {
|
||||
discard;
|
||||
}
|
||||
fragColor = u_color;
|
||||
// Para cualquier otro elemento no soportado pintamos una especie de rejilla
|
||||
// raruna.
|
||||
} else {
|
||||
|
|
Loading…
Add table
Reference in a new issue