DougHamil / threeagent

ClojureScript library for building Three.js apps in a reagent-like fashion
MIT License
134 stars 10 forks source link

Just black boxes! #23

Closed light-matters closed 3 years ago

light-matters commented 3 years ago

Just been playing with threeagent for the last half an hour/ hour and all I can see are black boxes in the browser. I tried to setup a minimal example with the following files:

<!DOCTYPE html>
<html class="no-js" lang="en">
<head>
    <title>A test of threejs</title>
    <style>
        body {
        padding: 0;
        margin: 0;
        overflow: none;
    }

     #root {
         width: 100%;
         height: 100%;
     }
    </style>
</head>
<body>
    <div id="app"></div>
    <canvas id="root"></canvas>
    <script src="scripts/main.js" type='text/javascript'></script>
</body>
</html>

shadow etc:

{:source-paths ["src"]

 :deps   {:aliases [:dev]}
 :nrepl {:middleware [refactor-nrepl.middleware/wrap-refactor]}
 :builds
 {:app {:target :browser
        :output-dir "public/scripts"
        :asset-path "/scripts"
        :modules {:main {:init-fn basic.main/init}}
        :devtools {:repl-pprint true
                   :http-root "public"
                   :http-port 3000}}}}

deps

{:paths ["src"]

 :aliases {:dev
           {:extra-deps {thheller/shadow-cljs {:mvn/version "RELEASE"}}
            ;; binaryage/devtools {:mvn/version "RELEASE"}
            }}
 :deps  {org.clojure/clojure       {:mvn/version "RELEASE"}
         org.clojure/clojurescript {:mvn/version "RELEASE"}
         reagent/reagent {:mvn/version "RELEASE"}
         doughamil/threeagent {:mvn/version "RELEASE"}}}

main.cljs

(ns basic.main
  (:require [threeagent.core :as th]))

;; Use reactive atom for storing state
(defonce state (th/atom {:ticks 0}))

;; Tick every second
(.setInterval js/window #(swap! state update :ticks inc) 1000)

;; Form-1 component example
(defn color-box [color size]
  [:box {:width size
         :height size
         :depth size
         :material {:color color}}])

;; Form-2 component example
(defn growing-sphere []
  (let [s (atom 0)]
    (.setInterval js/window #(swap! s inc) 5000)
    (fn []
      [:sphere {:radius @s}])))

;; Root component render function
(defn root []
  [:object {:position [1.0 0 0.0]
            :rotation [0 (js/Math.sin (:ticks @state)) 0]}
   [color-box "red" 1.0] ; Don't forget to use square brackets!
   [growing-sphere]])

;; Initialize and begin rendering threeagent scene

(defn init []
  (th/render root (.getElementById js/document "root")))

(defn ^:dev/after-reload on-code-reload [] ;; For hot-code reloading, just call the render function again
  (th/render root (.getElementById js/document "root")))

I'm not getting any errors in the console apart from: "The character encoding of the HTML document was not declared. The document will render with garbled text in some browser configurations if the document contains characters from outside the US-ASCII range. The character encoding of the page must be declared in the document or in the transfer protocol." which of course I assume is unrelated.

I tried the example on the github page and the example in the doc but no joy. I had a flick through the source and believe that the package is automatically adding a renderer but is it just that there's a camera missing or not in the right place or something simple?

I've never used three.js before. Any help would be much appreciated :).

Thanks.

light-matters commented 3 years ago

So, it turns out that I can see something if I add in some lighting. Even then though, it's just an edge so really it's better to change the positioning.

So, a few changes 'fixes' the example:

(defn lighting []
  [:object
   [:hemisphere-light {:intensity 0.4
                       :sky-color 0x8890FF
                       :position [0 5 10]}]])

(defn root []
  [:object {:position [0.0 0.0 -5.0]
            :rotation [0 (js/Math.sin (:ticks @state)) 0]}
   [color-box "red" 1.0]
   [growing-sphere]
   [lighting]])

As far as I can tell, this shouldn't be limited to my particular use case and I only started the issue here because this is really just following the examples in the doc. I'd be happy to help add some more content to the examples to avoid potential confusion for others?

DougHamil commented 3 years ago

You're absolutely right, the example code is no good without lighting added. Thank you for reporting this, I'd be happy to accept a PR for any doc changes!

tlonist-sang commented 3 years ago

@DougHamil Thanks for the great work. I have a question regarding black canvas as well.

From the example source code (https://github.com/DougHamil/threeagent-examples/tree/master/tetris) I found .setClearColor renderer 0xCCCCFF))

which I assume to be the line setting the color of the canvas. Applying this to the current version using re-frame + threeagent, it doesn't seem to work as expected. (in fact, not working at all!)

One thing I didn't do is to require "three" directly into the namespace. Is there any extra configuration for adding this external js library into ns? and is this necessary for using .setClearColor function in the project?

-- self answer turns out, you need to add ^js (js interop) in between the method you are calling and parameters. For example, (.renderer ^js ctx) instead of (.renderer ctx)

light-matters commented 3 years ago

You're absolutely right, the example code is no good without lighting added. Thank you for reporting this, I'd be happy to accept a PR for any doc changes!

Apologies, I was too slow to do anything like a pull request. To completely abuse the system however, (because I can't find your email address) can I invite you to present an introduction to our clojure data science community ? You can find me on the Clojure zulip chat: https://clojurians.zulipchat.com/#narrow/stream/150796-zulip