mirror of
https://github.com/penpot/penpot.git
synced 2025-02-01 20:09:04 -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-macros [app.util.gl.macros :refer [slurp]])
|
||||||
(:require
|
(:require
|
||||||
["gl-matrix" :as glm]
|
["gl-matrix" :as glm]
|
||||||
|
[app.common.data.macros :as dm]
|
||||||
[app.common.math :as math]
|
[app.common.math :as math]
|
||||||
[app.util.gl :as gl]
|
[app.util.gl :as gl]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
|
@ -15,6 +16,7 @@
|
||||||
|
|
||||||
#_(def shaders (js/Map.))
|
#_(def shaders (js/Map.))
|
||||||
(def programs (js/Map.))
|
(def programs (js/Map.))
|
||||||
|
(def program-actives (js/Map.))
|
||||||
#_(def textures (js/Map.))
|
#_(def textures (js/Map.))
|
||||||
#_(def framebuffers (js/Map.))
|
#_(def framebuffers (js/Map.))
|
||||||
|
|
||||||
|
@ -53,6 +55,25 @@
|
||||||
:bool 7
|
:bool 7
|
||||||
:frame 8))
|
: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
|
(defn resize-canvas-to
|
||||||
"Resize canvas to specific coordinates."
|
"Resize canvas to specific coordinates."
|
||||||
[canvas width height]
|
[canvas width height]
|
||||||
|
@ -75,28 +96,34 @@
|
||||||
(defn prepare-gl
|
(defn prepare-gl
|
||||||
"Prepares the WebGL context for rendering."
|
"Prepares the WebGL context for rendering."
|
||||||
[gl]
|
[gl]
|
||||||
(let [default-program (gl/create-program-from-sources gl default-vertex-shader default-fragment-shader)]
|
(let [default-program (gl/create-program-from-sources gl default-vertex-shader default-fragment-shader)
|
||||||
(.set programs "default" default-program)))
|
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
|
(defn render-gl
|
||||||
"Renders the whole document to the canvas."
|
"Renders the whole document to the canvas."
|
||||||
[gl objects vbox]
|
[gl objects vbox]
|
||||||
(let [projection (.create glm/mat3)
|
(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))
|
(.clear gl (.-COLOR_BUFFER_BIT gl))
|
||||||
|
|
||||||
(.viewport gl 0 0 (.-width (.-canvas gl)) (.-height (.-canvas gl)))
|
(.viewport gl 0 0 (.-width (.-canvas gl)) (.-height (.-canvas gl)))
|
||||||
|
|
||||||
;; Enable alpha blending
|
;; Enable alpha blending
|
||||||
(.enable gl (.-BLEND gl))
|
(.enable gl (.-BLEND gl))
|
||||||
(.blendFunc gl (.-SRC_ALPHA gl) (.-ONE_MINUS_SRC_ALPHA 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))
|
(println "---------------> vbox" (:x vbox) (:width vbox) (:y vbox) (:height vbox))
|
||||||
(.uniformMatrix3fv gl (.getUniformLocation gl (.get programs "default") "u_projection") false projection)
|
(.uniformMatrix3fv gl (gl/get-program-uniform-location actives "u_projection") false projection)
|
||||||
(.uniform4f gl (.getUniformLocation gl (.get programs "default") "u_vbox") (:x vbox) (:y vbox) (:width vbox) (:height vbox))
|
(.uniform4f gl (gl/get-program-uniform-location actives "u_vbox") (:x vbox) (:y vbox) (:width vbox) (:height vbox))
|
||||||
|
|
||||||
(doseq [[_ object] objects]
|
(doseq [[_ object] objects]
|
||||||
(let [selrect (:selrect object)
|
(let [selrect (:selrect object)
|
||||||
|
@ -105,25 +132,25 @@
|
||||||
width (:width selrect)
|
width (:width selrect)
|
||||||
height (:height selrect)
|
height (:height selrect)
|
||||||
rotation (:rotation object)
|
rotation (:rotation object)
|
||||||
;; Tengo que encontrar la forma de "reordenar la matriz" para que funcione la
|
border (get-object-border-radius-as-vec4 object)
|
||||||
;; rotación.
|
type (get-object-type-as-int object)]
|
||||||
;; transform (:transform object)
|
(js/console.log border)
|
||||||
;; {a :a b :b c :c d :d e :e f :f} transform
|
(.uniform4fv gl (gl/get-program-uniform-location actives "u_border") border)
|
||||||
;; matrix #_(js/Float32Array. #js [a c 0 b d 0 0 0 1])
|
(.uniform1i gl (gl/get-program-uniform-location actives "u_type") type)
|
||||||
matrix (js/Float32Array. #js [1 0 0 0 1 0 0 0 1])
|
(.uniform2f gl (gl/get-program-uniform-location actives "u_size") width height)
|
||||||
fill (first (:fills object))]
|
(.uniform2f gl (gl/get-program-uniform-location actives "u_position") x y)
|
||||||
(js/console.log "fill" fill)
|
(.uniform1f gl (gl/get-program-uniform-location actives "u_rotation") (/ (* rotation js/Math.PI) 180.0))
|
||||||
(js/console.log "matrix" matrix)
|
#_(.uniformMatrix3fv gl (gl/get-program-uniform-location actives "u_transform") false 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)
|
|
||||||
;; NOTA: Esto es sólo aplicable en objetos que poseen fills (los textos no
|
;; NOTA: Esto es sólo aplicable en objetos que poseen fills (los textos no
|
||||||
;; poseen fills).
|
;; poseen fills).
|
||||||
(doseq [fill (reverse (:fills object))]
|
(doseq [fill (reverse (:fills object))]
|
||||||
(do
|
(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)))))))
|
(.drawArrays gl (.-TRIANGLE_STRIP gl) 0 4)))))))
|
||||||
|
|
||||||
(mf/defc canvas
|
(mf/defc canvas
|
||||||
|
|
|
@ -57,13 +57,15 @@
|
||||||
[parameter get-active-name get-location-name]
|
[parameter get-active-name get-location-name]
|
||||||
(fn [gl program]
|
(fn [gl program]
|
||||||
(let [count (.getProgramParameter gl program parameter)
|
(let [count (.getProgramParameter gl program parameter)
|
||||||
get-active (dm/get-prop gl get-active-name)
|
get-active (unchecked-get gl get-active-name)
|
||||||
get-location (dm/get-prop gl get-location-name)]
|
get-location (unchecked-get gl get-location-name)
|
||||||
(into {} (for [index (range count)]
|
actives #js {}]
|
||||||
(let [info (get-active gl program index)
|
(doseq [index (range 0 count)]
|
||||||
name (.-name info)
|
(let [info (.apply get-active gl #js [program index])
|
||||||
location (get-location gl program name)]
|
name (.-name info)
|
||||||
[name #js {:name name :info info :location location}]))))))
|
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-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"))
|
(def get-program-attributes (get-program-active-factory (.-ACTIVE_ATTRIBUTES js/WebGLRenderingContext) "getActiveAttrib" "getAttribLocation"))
|
||||||
|
@ -75,6 +77,13 @@
|
||||||
attributes (get-program-attributes gl program)]
|
attributes (get-program-attributes gl program)]
|
||||||
#js { :uniforms uniforms :attributes attributes }))
|
#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
|
;; Buffers
|
||||||
;;
|
;;
|
||||||
|
@ -90,9 +99,19 @@
|
||||||
;; Framebuffers
|
;; Framebuffers
|
||||||
;;
|
;;
|
||||||
(defn create-framebuffer
|
(defn create-framebuffer
|
||||||
[gl]
|
[gl attachments]
|
||||||
(let [framebuffer (.createFramebuffer gl)]
|
(let [framebuffer (.createFramebuffer gl)]
|
||||||
(.bindFramebuffer gl framebuffer)
|
(.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)
|
(.bindFramebuffer gl nil)
|
||||||
framebuffer))
|
framebuffer))
|
||||||
|
|
||||||
|
|
|
@ -17,26 +17,45 @@ out vec4 fragColor;
|
||||||
in vec2 v_texCoord;
|
in vec2 v_texCoord;
|
||||||
|
|
||||||
uniform int u_type;
|
uniform int u_type;
|
||||||
|
uniform vec2 u_size;
|
||||||
uniform vec4 u_color;
|
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() {
|
void main() {
|
||||||
// Si es un rect o un frame, simplemente asignamos el color al fragColor.
|
// Si es un rect o un frame, simplemente asignamos el color al fragColor.
|
||||||
if (u_type == type_rect || u_type == type_frame) {
|
if (u_type == type_rect || u_type == type_frame) {
|
||||||
fragColor = u_color;
|
if (isRoundedRect(u_border)) {
|
||||||
// Si es un circulo, comprobamos que el pixel este dentro del circulo, en caso
|
if (sdRoundBox(v_texCoord - 0.5, vec2(0.5), u_border / u_size.x) > 0.0) {
|
||||||
// contrario descartamos el pixel.
|
discard;
|
||||||
} else if (u_type == type_circle) {
|
}
|
||||||
if (length(v_texCoord - 0.5) > 0.5) {
|
fragColor = u_color;
|
||||||
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);
|
|
||||||
} else {
|
} else {
|
||||||
fragColor = u_color;
|
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
|
// Para cualquier otro elemento no soportado pintamos una especie de rejilla
|
||||||
// raruna.
|
// raruna.
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Reference in a new issue