我正在尝试使用OpenGL和GLSL实现八叉树遍历方案,并希望将数据保留在纹理中.虽然有很多种格式可用于纹理数据(不同大小的浮点数和整数),但我有一些麻烦,想知道是否有办法对位进行更精确的控制,从而实现更高的效率和紧凑的存储.这可能是一个普遍的问题,不仅适用于OpenGL和GLSL.
作为一个简单的玩具示例,假设我有一个包含16位整数的纹素.我想编码两个每个1位的布尔值,一个10位整数值,然后一个4位整数值到这个纹素.是否有一种技术可以在创建纹理时对其进行编码,然后在使用GLSL着色器对纹理进行采样时对这些组件进行解码?
编辑:看起来我实际上正在寻找位操作技术.由于它们似乎得到了支持,经过一些研究后我应该没问题.
我正在实现一个体素八叉树raycaster,剩下的唯一的事情是重新排列数据以填充八叉树的叶级别,以便可以对数据进行平均以构建树的较低级别.
为了方便起见,我最初想的是2D(四叉树).我的数据如图中左侧所示,我现在能够像右边那样重新排列.例子是8x8
.
但是,我意识到我需要按节点顺序排序数据,如下图所示:
换句话说,我想从一个数组对应的索引这样的索引:
[0 1 2 3 4 5 6 7 8 9 ... 63]
Run Code Online (Sandbox Code Playgroud)
到具有此顺序数据的数组:
[0 1 4 5 16 17 20 21 2 3 ... 63]
Run Code Online (Sandbox Code Playgroud)
对于8x8
四叉树的例子.
我无法弄清楚该怎么做.我的主要问题是处理任意树大小.如果我事先知道大小,我可能会硬编码一组嵌套循环,但它显然不是一个伟大或优雅的解决方案.我在想可能有一种递归方式来实现它.
这就是我用图1中描述的方式对数据进行排序的快速和脏的草图.它基本上是通过跟踪原始数据中的四个位置,然后在新阵列填满时将它们向前移动.据我所知,这个工作正常,但不能扩展到我的需要:
int w = 8;
int[] before = new int[w*w*w];
int[] after = new int[w*w*w];
for (int i=0; i<w*w*w; i++) {
before[i] = i;
}
int toFill = 0;
int front = 0;
int back = w;
int frontZ = w*w;
int backZ = w*w …
Run Code Online (Sandbox Code Playgroud) 我确信之前已经回答了,但我找不到一个好的解释.
我正在编写一个图形程序,其中部分管道正在将体素数据复制到OpenCL页锁定(固定)内存.我发现这个复制程序是一个瓶颈,并对一个简单的性能做了一些测量std::copy
.数据是浮点数,我要复制的每个数据块大小约为64 MB.
这是我的原始代码,在任何基准测试尝试之前:
std::copy(data, data+numVoxels, pinnedPointer_[_index]);
Run Code Online (Sandbox Code Playgroud)
data
浮点指针在哪里,numVoxels
是unsigned int,pinnedPointer_[_index]
是引用固定OpenCL缓冲区的浮点指针.
由于我的性能很慢,我决定尝试复制较小的数据部分,看看我得到了什么样的带宽.我使用boost :: cpu_timer进行计时.我已经尝试运行它一段时间以及平均数百次运行,得到类似的结果.以下是相关代码以及结果:
boost::timer::cpu_timer t;
unsigned int testNum = numVoxels;
while (testNum > 2) {
t.start();
std::copy(data, data+testNum, pinnedPointer_[_index]);
t.stop();
boost::timer::cpu_times result = t.elapsed();
double time = (double)result.wall / 1.0e9 ;
int size = testNum*sizeof(float);
double GB = (double)size / 1073741842.0;
// Print results
testNum /= 2;
}
Copied 67108864 bytes in 0.032683s, 1.912315 GB/s
Copied 33554432 bytes in 0.017193s, 1.817568 GB/s
Copied 16777216 …
Run Code Online (Sandbox Code Playgroud) 我一直在遵循使用 ASP.NET Core 中的集成测试中的 Microsoft 文档为 ASP.NET Core 2.2 API 设置测试的策略。
总而言之,我们扩展和定制WebApplicationFactory
并使用IWebHostBuilder
来设置和配置各种服务,以使用内存数据库为我们提供数据库上下文以进行如下测试(从文章中复制和粘贴):
public class CustomWebApplicationFactory<TStartup>
: WebApplicationFactory<TStartup> where TStartup: class
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
// Create a new service provider.
var serviceProvider = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();
// Add a database context (ApplicationDbContext) using an in-memory
// database for testing.
services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseInMemoryDatabase("InMemoryDbForTesting");
options.UseInternalServiceProvider(serviceProvider);
});
// Build the service provider.
var sp = services.BuildServiceProvider();
// Create a …
Run Code Online (Sandbox Code Playgroud) 我正在使用Angular 1前端,与一个非常标准的REST-ish API交谈.一般结构由简单的HTML视图组成,相应的控制器与一些基本URL相交,在没有每个控制器的情况下通常保持相同,例如/customer
在这个简化的示例中:
调节器
app.controller('customerCtrl', function($scope, $http) {
$scope.loadCustomer = function() {
$http.get('/customer/'+$scope.id)
.then(function(response) {
$scope.customer = response.customer;
});
};
$scope.loadCustomerData = function() {
$http.get('/customer/'+$scope.id+'/data')
.then(function(response) {
$scope.customerData = response.data;
});
};
});
Run Code Online (Sandbox Code Playgroud)
视图
<div ng-controller="customerCtrl">
<input type="text" ng-model="id"></input>
<button ng-click="loadCustomer()">Load Customer</button>
<div>{{ customer.name }}</div>
...
...
</div>
Run Code Online (Sandbox Code Playgroud)
等等.实际文件长度为几百行.现在突然间,一组新用户需要访问该应用程序.前端视图和控制器逻辑是相同的,但它们跟一个不同的后端基本URL,例如/externalCustomer
.加载函数调用将改为$http.get('/externalCustomer/'+$scope.id)
,等等.
该意见还需要不同的URL.如果访问当前视图http://app.com/#/customerView
,新的视图将在http://app.com/#/externalCustomerView
.
鉴于有更多这样的视图和控制器方法(带有硬编码的后端URL),我宁愿不复制和粘贴几百行并且逻辑分歧,实现这个的正确方法是什么?能够重用视图和控制器并且可能传递一些基本URL参数和/或视图URL会很棒,但我不知道如何开始.